Python thread yardım!

arkadaşlar bir sorunum var. thread konusuna çok yabancıyım. hatta hiçbirşey bilmiyorum. fakat sorunum ile ilgili tek bir örnek gösterirseniz ben devamını getiririm. şöyle bir örnek üzerinden sorunumu anlatayım. python3.7 kullanıyorum.

def yazdır(isim):
    print("benim adım : ", isim)

#bu listede 10 tane isim var ama siz 1000 isim varmış gibi düşünün
liste = ["ali","mehmet","effe","erkan","mustafa","kadir","suzan","cafer","kamil","rıza"]

for isim in liste:
    yazdır(i)

şimdi arkadaşlar yukarıdaki işlem benim programda kullanacağım birşeye yakın. yani liste içinde normalde isim değilde , url adresi var ve bu url adresleri ile request gönderiyorum . bu yüzden yavaş ilerliyor.çünkü çok url var. yukarıdaki örnek için bir çözüm , gerçek programımda da çözüm olacaktır.

şimdi ben 10 tane thread kullanmak istiyorum. bu 10 thread aynı anda başlayacak , her thread liste içindeki elemanları 0. indexten başlayıp , yazdır fonksiyonuna gönderecek. yanlız thread1 ali ismini fonksiyona gönderirken , thread2 de mehmet ismini fonksiyona gönderecek. yani bir threadin fonksiyona gönderdiği ismi , diğer thread alıp fonksiyona göndermeyecek. listenin en başından başlayıp, liste içindeki elemanlar bitene kadar fonksiyona gönderecek. aynı anda başlayıp bu işi yapması gerekiyor. çünkü en sonra denediğim url listem 28600 tane url vardı. tek tek request gönderirsem bitmiyor. çok üzün sürüyor. bu yüzden thread kullanmak istiyorum. cevaplarınızı dört gözle bekliyorum. buradaki ilk konum. yanlış bir şekilde konu açtıysam herkesden özür dilerim…

Merhaba, şu başlığı da bir incelemenizi öneririm.

Sorunuza gelecek olursak, verdiğiniz örnek için threading modülü şöyle kullanılabilir:

import threading


def yazdir(isim):
    print("benim adım : ", isim)


liste = [
    "ali", "mehmet", "effe", "erkan", "mustafa", 
    "kadir", "suzan", "cafer", "kamil", "rıza"
]

for isim in liste:
    t = threading.Thread(target=yazdir, args=(isim,))
    t.start()

Bu arada Threadler aynı anda başlamaz.

1 Beğeni

Burada tutarsizlik var. Her thread 0’dan baslarsa hepsi ali'yi (ilk elemani) gonderir.

Dagitimi merkezi bir yerden yapmak daha mantikli. Her thread listeyi alip belirli elemanlari fonksiyona paslamaktansa her thread belirli elemanlari alip aldiklarini sirayla fonksiyona paslasin.

Bu arada request gonderdigin kutuphane multithreading destekliyor mu? Konuyla ilgili gotcha’lari/caveat’leri var mi?

Koda da thread numarasini parametre olarak alan bir fonksiyonu n kere cagirarak baslayabilirsin:

def thread_main(thread_number, baska, data, filan):
    print("%d. thread'den selamlar" % (thread_number,))

for i in range(10):
    thread_main(i, None, False, 42)

Buradan gercek thread’lere gecmek cok kolay. (Yukaridaki ornekte de var; threading.Thread(target=thread_main).start())

1 Beğeni

Selamun Aleyküm, konu ile ilgili bilgim yok. Siz konu açınca öğrenmek için merak edip biraz araştırdım. Aşağıdaki bağlantı belki işinize yarar.

1 Beğeni

öncelikle cevap yazdığın için teşekkür ederim. yukarıdaki gösterdiğin örnek de kaç thread bu fonksiyona isim gönderiyor ?

threadların aynı anda başlamadığını yabancı bir forumda okumuştum. fakat saniye olarak diğer thread’ı sonra başlatılabiliyormuş. ilk thread başladıktan sonrra ikinci thread 0.5 saniye sonra başlayabilir diye okumuştum. fakat yabancı forum olduğu için çok iyi sayfa türkçeye çevrilmediğinden tam analamayadım.

ayrıca bir de yukarıdaki örnek de queue modülünün kullanılması faydalı olur mu ?

Listenin eleman sayisi kadar Thread sinifindan nesne olusturuluyor. Butun threadler ayni fonksiyonu hedef aliyor ama her defasinda listeden farkli elemanlar arguman olarak seciliyor.

Yani i = "ali" iken yazdir() fonksiyonunun isim argumani "ali",
i = "mehmet" iken yazdir() fonksiyonunun isim argumani "mehmet" olarak seciliyor.

Queue modulunu pek kullanmadim. O yüzden yorum yapamayacağim.

senin gösterdiğin gibi kullanmak , hiç thread kullanmamaktan daha hızlı ilerliyor olmalıdır.

değerli görüşünü paylaştığın için teşekkürler

Threadler ayni anda baslamiyor ama ayni anda birden cok islemin yapilmasina olanak saglamak icin kullaniliyor. Mesela iki fonksiyon icinde birer tane while dongumuz var. Iki dongunun de ayni anda calisir durumda olmasini istiyoruz diyelim. Boyle bir durumda thread kullaniriz. Eger kullanmazsak, bir while dongusu sonlanmadan digeri baslamaz.

Yani bir islemin bitmesini beklemeden baska bir islemi de baslatmak icin (es zamanli islemler olusturmak icin) Thread kullanilir.

peki şöyle birşey olabilir mi !

2 farklı liste olsa ve her thread farklı listeleri aynı fonksiyona gönderirse ?

Olabilir evet. Ama yukarida ilk paylastigim ornek icin thread kullanmaya gerek yok. Bir de ayni for fongusunde iki adet liste kullanacaksaniz listelerin uzunlugunun esit olmasina dikkat edin.

import threading


def yazdir(isim):
    print("benim adım : ", isim)


liste1 = [
    "ali", "mehmet", "effe", "erkan", "mustafa", 
    "kadir", "suzan", "cafer", "kamil", "rıza"
]

liste2 = range(len(liste1))

for isim, numara in zip(liste1, liste2):
    t1 = threading.Thread(target=yazdir, args=(isim,))
    t2 = threading.Thread(target=yazdir, args=(numara,))
    t1.start()
    t2.start()

peki anladım teşekkürler

Aşağıdaki örneği, threadler hakkında biraz daha bilgi sahibi olmak için inceleyebilirsiniz.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import threading

# global bölgede bir tane data değişkeni tanımlayalım.
# Değeri None olsun.
data = None


def f1():
    # global bölgedeki data'yı local bölgeye çekiyoruz.
    global data
    while True:
        # Döngü içindeki data'ya tekrar tekrar yeni değerler veriyoruz.
        data = input(">>> ")
           

# f1() fonksiyonunu hedef alan bir tane thread nesnesi oluşturalım.
t1 = threading.Thread(target=f1)
# Bu thread'in daemon özelliğini True yaparsak. Bütün aktif threadler
# sonlandığında bu thread de sonlanır. daemon'u start() fonksiyonunu
# çalıştırmadan önce aktif etmek gerekir.
t1.daemon = True
t1.start()

                    
def f2():
    while data != "q":  # data q'ya eşit olmadığı sürece
        continue        # döngü devam etsin.
    else:               # Döngü sonlanırsa
        t1.join(5)      # t1 thread'i 5 saniye içerisinde sonlansın.
        print()         # Zaten else durumuna eğer başka işlemler 
                        # yazmazsak yapılacak işlem kalmadığı için 
                        # t2 otomatik olarak sonlanacaktır. 
                        # t2 sonlandığı zaman, t1 de daemon'u
                        # True olarak ayarlandığı için sonlanır. 
                        # Çünkü aktif thread kalmıyor. Ama biz
                        # burada t1 5 saniye sonra sonlansın diye 
                        # bir koşul koyuyoruz.  Yani data = "q"
                        # olursa, 5 saniye içinde program kapanır.


t2 = threading.Thread(target=f2)
t2.start()
1 Beğeni

Evet, bu work queue veya worker pool dedigimiz pattern ve distributed versiyonu yaklasik 4 senedir faturalarimi oduyor. Esit sayi yerine esit is dagitimi saglamasi gibi guzellikleri var.

1 Beğeni

Threading modülünü birşekilde kullanıyorum. Eskiye nazaran denemeler daha hızlandı. Aws s3 kovaları kontrolü yapıyorum. Mesala listemde 28.000 kelime var. For döngüsü ile her bir elemanı alıp s3 kova sorgusu için yaptığım fonksiyona gönderiyorum. Threading ile çok hızlı işlem yapıyordu ama python hatalar vermeye başladı. Bence sorguyu çok hızlı yapıyor diye timeout hatalarıydı yanlış hatırlamıyorsam . Daha sonra thread için .join() kullanınca hata düzeldi ama hızı da düştü. Daha sonra nasıl bir çare bulabilirim dedim , tekrar .join 'i sildim yerine time.sleep(0.2) kullanmaya başladım. Şuan hata vermiyor. .join kullanmaktan 1 tık daha hızlı ama listenin sonunu getirmem yine saatleri buluyor. Bu işi çok daha pratik hale getirmem gerekiyor. Şöyle birşey yapmayı düşünüyorum ama bir bilgim yoktur. Linux kullanıyorum. 28.000 tane kelimeden oluşan listeyi 5 parçaya bölmeyi düşünüyorum. Programı başlattığımda ve işlemler çalışmaya başladığında 5 farklı terminalin açılmasını sağlayacağım. Her terminal ayrı process pid değerleri olacak. Her bir terminal (uç birim) kendine ayrılmış listeyi deneyecek. Böylece işlem daha hızlı olacak. Genel de bu tür programlar wifi evil twin ataklarda yapılıyor. Bşr terminal deauth saldırı yapıyor, diğer terminal spoofing yapıyor, diğer terminal kullanıcının şifre girip girmediğini gösteriyor. Paralel olarak aynı anda ancak bu şekilde programı çalıştırabileceğimi düşünüyorum. Threading ile aynı anda aynı işi yapacak 2 ayrı fonksiyon yaptım . Thread1 ve thread2 yi başlattım , fakat birşe kilde hata almaya başladım. Ayrı pid değerleri ve ayrı terminaller olursa bunu aynı anda 5 terminale bölerek yapabileceğimi düşünüyorum. Bu konuda bir fikriniz varsa benimle paylaşın lütfen. Bug bounty programlarına katılıyorum, zaman benim için çok önemli. 28.000 tane bir listeyi 1 saatte denesem yine kafidir. Fakat şu şartlardq 2- 2.5 saat zamanım gidiyor bir web site için kova taramam…

Aciklaman kodla (veya pseudokodla) beraber gelmedigi icin pek bir sey ifade etmiyor. Tek soyleyebilecegim, sistemdeki race condition’lari elimine edememissin.

Hata cikinca join denemen, devam edince sleep denemen cargo cult programming/programming by permutation’a isaret. Tavsiyem, hatalarin niye ciktigini ve muhtelif cozumler deneyince neden devam ettigini arastirip ogrenmen, ona gore dogru cozumu uygulaman.

Thread yerine process kullanman, (varsa) multi-threading destegi olmayan 1-2 miyop kutuphanenin calismasi disinda hic bir problemini cozmeyecek; dahasi thread’ler arasi iletisim process’ler arasi iletisime donusecegi icin bir kisim zorlasacak.

Terminalin process pid degerine donusmesinden ne kastettigini anlamadim. Her terminalde ayri bir process calisacak mi demek istiyorsun?

Basitce multiprocessing’i aciklamissin. Butun modern isletim sistemleri bu sekilde calisiyor, neden ozellikle evil twin atagi ornegini verdigini anlamadim.

Multiprocessing paralel bilgi isleme yontemlerinden sadece bir tanesi. Bahsettigimiz multithreading bir baskasi, ve parcalarin birbirleriyle iletisim halinde olmasi gerektigi zaman daha kolay bir model.

O zaman birşe kilde düzelt demekten baska bir sey gelmiyor elimden :slight_smile:

Gayet mumkun, fakat bu 5 terminalin isi aralarinda nasil boleceklerini, sonuclari nereye raporlayacaklarini vs. cikartman lazim. 6. bir kontrol process’i kullanmayi dusunebilirsin.

1 Beğeni

Hocam size kodu özelden yollayabilirmiyim? Bir inceleseniz? Zaten herşey yapılmış. Sadece programı hızlandırmak için ekstra ne yapılabilir ona bakmanız gerekyr. Sadece 1 sayfalık kod. Fazla değil. Buradan özelden yollanabiliyorsa buradan , yollanmıyorsa maillden yollayablrmym? Belki siz daha kolay bir çare bulursunuz

Buraya yazarsan daha cok insan yardimci olabilir.