Threading Eş Zamanlı Kullanımı Nasıl Oluyor

Merhaba, programlamaya yeni başladım ve küçük küçük programlar yazıyorum. Threading konusunda ise kafam karıştı nette ki tüm Türkçe döküman ve videolara baktım, sormak istediğim ise; Mesela bir metin dosyası içinde 10.000 site var bu sitelere requests ile istek atıp tüm içerikleri alacağım bunu thread ile daha kısa zaman da yapabilir miyim? Bir web sayfasına istek atarken aynı anda isteği bir dosyaya kaydedebilirim threads sayesinde bunda hemfikiriz, ama binlerce sayfaya istek attığım zamanı da kısaltmaya yararmıyor mu? Yoksa bunu multi process ile mi yapmalıyım ? Alttaki program da bu siteden yararlandım. Ben mi hata yapıyorum yoksa threading ile uzun süren tekrarlanabilir işleri kısaltmaya yaramıyor mu? Bazı programlarda görmüşsünüzdür --thread argümanı vardır --thread=1 derseniz uzun sürer --thread=20 derseniz kısa sürer bu tarzda bir şey yapmak istedim ama durum hüsran

import threading

import requests

sites = ["http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://fatihmertdogancan.wordpress.com",
     "http://ozgurerdogdu.blogspot.com/",
     "http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://fatihmertdogancan.wordpress.com",
     "http://ozgurerdogdu.blogspot.com/",
     "http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://fatihmertdogancan.wordpress.com",
     "http://ozgurerdogdu.blogspot.com/",
     "http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://fatihmertdogancan.wordpress.com",
     "http://ozgurerdogdu.blogspot.com/"
     "http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://fatihmertdogancan.wordpress.com",
     "http://ozgurerdogdu.blogspot.com/",
     "http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://fatihmertdogancan.wordpress.com",
     "http://ozgurerdogdu.blogspot.com/",
     "http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://fatihmertdogancan.wordpress.com",
     "http://ozgurerdogdu.blogspot.com/",
     "http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://fatihmertdogancan.wordpress.com",
     "http://ozgurerdogdu.blogspot.com/"
     "http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://fatihmertdogancan.wordpress.com",
     "http://ozgurerdogdu.blogspot.com/",
     "http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://fatihmertdogancan.wordpress.com",
     "http://ozgurerdogdu.blogspot.com/",
     "http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://fatihmertdogancan.wordpress.com",
     "http://ozgurerdogdu.blogspot.com/",
     "http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://fatihmertdogancan.wordpress.com",
     "http://ozgurerdogdu.blogspot.com/"

     ]


def craw():
for site in sites:
    r = requests.get(site)
    print(r.content)


t1 = threading.Thread(target=craw)
t1.start()

craw()

Fonksiyonların eş zamanlı çalışmasını istiyorsanız, craw fonksiyonunu değil de, bu fonksiyondaki for döngüsünde çağırdığınız request fonksiyonunu hedef alan Thread nesneleri tanımlamanız gerekiyor.

import requests

from threading import Thread
from datetime import datetime


sites = [
    "http://yasararabaci.tumblr.com",
    "http://metehan.us",
    "http://blog.tanshaydar.com",
    "http://fatihmertdogancan.wordpress.com",
    "http://ozgurerdogdu.blogspot.com/",
    "http://yasararabaci.tumblr.com",
    "http://metehan.us",
    "http://blog.tanshaydar.com",
    "http://yasararabaci.tumblr.com",
    "http://metehan.us",
    "http://blog.tanshaydar.com",
    "http://fatihmertdogancan.wordpress.com",
    "http://ozgurerdogdu.blogspot.com/",
    "http://yasararabaci.tumblr.com",
    "http://metehan.us",
    "http://blog.tanshaydar.com",
    "http://fatihmertdogancan.wordpress.com",
    "http://ozgurerdogdu.blogspot.com/",
    "http://yasararabaci.tumblr.com",
    "http://metehan.us",
    "http://blog.tanshaydar.com",
    "http://fatihmertdogancan.wordpress.com",
    "http://ozgurerdogdu.blogspot.com/"
]
         
         
def target(site):
    print(f"Started at: {datetime.now()}")
    r = requests.get(site)
    print(f"Finished at: {datetime.now()}")


def craw():
    start_time = datetime.now()
    for site in sites:
        Thread(target=target, args=(site,)).start()


craw()

Hocam yazdığınızdan beri bakıyorum yazdığım diğer scriptlere de bu mantığı uydulamaya çalışıyorum. Sorudaki kodları değiştirdim şu an da bu program ortalama 40 saniye de çalışıyor(ayrıca zamanı kısaltmak bir yana her siteyi 2 kere çekiyor) ve duruyor. Bu süreyi threading ile düşürebilir misiniz ?

Kodları nasıl değiştirdiniz, bir bakabilir miyiz?

Hocam konuyu ilk açtığım post içersinde kodları güncelledim demek istedim. İlk post içindeki kodlar hocam

Hayır işte öyle yapmayacaksınız. Sizinle paylaştığım kodları kullanmadınız mı yoksa?

import threading
import time

import requests

sites = ["http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://fatihmertdogancan.wordpress.com",
     "http://ozgurerdogdu.blogspot.com/",
     "http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://fatihmertdogancan.wordpress.com",
     "http://ozgurerdogdu.blogspot.com/",
     "http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://fatihmertdogancan.wordpress.com",
     "http://ozgurerdogdu.blogspot.com/",
     "http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://fatihmertdogancan.wordpress.com",
     "http://ozgurerdogdu.blogspot.com/"
     "http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://fatihmertdogancan.wordpress.com",
     "http://ozgurerdogdu.blogspot.com/",
     "http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://fatihmertdogancan.wordpress.com",
     "http://ozgurerdogdu.blogspot.com/",
     "http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://fatihmertdogancan.wordpress.com",
     "http://ozgurerdogdu.blogspot.com/",
     "http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://fatihmertdogancan.wordpress.com",
     "http://ozgurerdogdu.blogspot.com/"
     "http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://fatihmertdogancan.wordpress.com",
     "http://ozgurerdogdu.blogspot.com/",
     "http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://fatihmertdogancan.wordpress.com",
     "http://ozgurerdogdu.blogspot.com/",
     "http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://fatihmertdogancan.wordpress.com",
     "http://ozgurerdogdu.blogspot.com/",
     "http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://fatihmertdogancan.wordpress.com",
     "http://ozgurerdogdu.blogspot.com/"

     ]


def craw(site, i):
    r = requests.get(site)
    
    with open(f"Test/index_{i}.html", "w") as f:
        f.write(r.text)
    
    print(f"{site} completed")
    
    global threads
    threads -= 1

s = time.time()

i = 0
threads = 0
while i < len(sites):    
    if threads < 4:
        site = sites[i]        
        t = threading.Thread(target=craw, args=(site,i,))
        t.start()        
        
        threads += 1
        i += 1
    
    else:
        continue

e = time.time()

print(e-s)

Merhaba, şöyle bir şey yazdım. Aynı anda 5 Thread çalışıyor, biri bittiğinde diğerine başlıyor. Craw fonksiyonu içerisinden site ile alakalı yapmak istediklerinizi yazabilirsiniz. Ben Test klasörü içerisine kaydetmeyi tercih ettim.

Hepsini aynı anda çalıştırmak varken neden 5’er 5’er çalıştırıyorsunuz? Zaten bu web sitesi listesindeki ilk 5 site sürekli tekrar ediliyor. Listede tekrar eden siteleri kaldırmak lazım.

  1. Site listesine dikkat etmedim örnek bir liste olduğunu düşünerek.
  2. 5 er 5 er çalıştırma sebebim de aslında fazla yük bindirmemek ve Thread sayısını kullanıcıya bırakmak diyebilirim. Bir de soruda “mesela bir metin dosyası içinde 10.000 site var” diyor bi anda binlerce Thread oluşturmak fazla yük bindirmeyecek midir?

Bu arada az önce yanlışlıkla size cevap olarak yazmışım

Ben de hangi amaçla aynı anda 10000 siteye bağlanılır diye düşünüyorum. Bir insan 10000 siteye aynı anda bağlanıp ne yapmak isteyebilir ki :slight_smile:

Kullandım fakat sorumu anlamadığınzı gördüm sadece kodlardan datetime modülünü çıkardım sorum ile alakası yok, koda bakınca hemen anlarsınız sandım. Verdiğiniz kodların istediğim ile alakası olmamak ile birlikte kafamı karıştır ekrana sadece zaman vuran bir script olmuştu hocam, Kodlar içersinde print(r.content) çıkarmışsınız o satır özellikle program uzun sürsün diye eklemiştim. Kısacası verdiğim kodları değiştirince ve farklı bir sonuç verince hiçbir şey anlamadım kafanız karışmasın diye datetime sildim.

soruda dediğim gibi o siteleri farklı siteler yapmak uzun süreceğinden bunu da konuda açıkladığım üzere, o siteleri her biri farklı olarak görmelisiniz hocam

Çok teşekkür ederim hocam bu 5 Threadin hepsini aynı anda kullanıp her biri farklı siteye gidip aynı anda sonuç döndürme gibi bir durum var mı bilginiz var mı hocam. Normal program 5 saniye de 5 site çekerken, 5 thread ile çalışan program 1 saniye de 5 site çekebilir mi ?

Ekrana yazı yazmak mantıklı bir performans ölçüsü değil.

Performans için değil ki bunu yapmam işlem uzun sürsün istedim. Böylece normal program 10 saniyede çalışıp sonuç üretirken Thread ekledikten sonra kaç saniye sürecek , Thread ne derece etki edecek diye görmek istedim. Performans ölçüsünü nereden çıkardınız?

Performansın programın çalışma süresi ile bağlantılı olduğunu düşünerek yazdım onu.

Sizin deyiminizle “bir insan” 10.000 siteye;
1.Belirli anahtar kelimelerin hangi sayfa da geçtiğini görmek için bağlanabilir (User-Pass, yükselen trend anahtar kelime vs…)
2.Liste içinde ki her siteye güvenlik amaçlı test yaklaşımı ile çeşitli varyasyonlar ile saldırı yapmak için(Kaba Kuvvet, otomatik SQL, XSS vs …)
3.Tamamen sistem kaynaklarını test etmek için
4.Kullanacağı kütüphanenin(program, kütüphane vs ) etkisini test etmek için bağlabilir

10 saniye de aklıma gelenler bunlar

Evet.

Belli bir thread sayısından sonra faydası değil zararı olur, doğru.

Yavaşlığın asıl sebebi cihazımızdan bağımsız etkenlerin sebep olduğu IO’daki bekleme olduğu için şart değil.

Yazdığınız kod teoride aynı işi yapan ve tek thread ile çalışan bir koddan iki kat hızlı. Ama yazdığınız koda bakınca thread’ları nasıl kullanacağınızı anlamadığınızı düşünüyorum.

Ana thread’daki while döngüsü gereksiz yere performansı yiyor. Aşağıdaki gibi concurrent.futures.ThreadPoolExecutor kullanmak daha iyi.

İnternet bağlantısının hızı sınırlı olduğu için belli bir yerden sonra thread sayısını arttırmak anlamsız olabilir.

Verilen örnek kod istediğiniz şekilde birden fazla thread kullanarak çalışıyor.


Benin önerim ThreadPoolExecutor kullanılması:

from concurrent.futures import ThreadPoolExecutor
import requests
from time import sleep

sites = ["http://yasararabaci.tumblr.com",
     "http://metehan.us",
     "http://blog.tanshaydar.com",
     "http://fatihmertdogancan.wordpress.com",
     "http://ozgurerdogdu.blogspot.com/"] * 20

def geturls(urls):
    global donned
    for url in urls:
        requests.get(url)
    donned += 1
    print("Done")


def main(sites, maxworkers):
    pool = ThreadPoolExecutor(max_workers=maxworkers)
    for i in sites:
        pool.submit(geturls, (i,))
    while donned < 100:
        sleep(1)
    
if __name__ == "__main__":
    donned = 0
    main(sites, 20)
2 Beğeni

Zaten dediğiniz şey Threadin yaptığı şey. Thread sayesinde fonksiyonlar aynı anda çalışıyor. Siz craw fonksiyonu içerisine site ile ne yapmak istiyorsanız yazabilirsiniz. Ben sadece ek olarak Thread sayısını sınırladım. Yani liste uzunluğu kadar Thread oluşturmaktansa bunu kullanıcıya bırakmayı tercih ettim.

Hocam çok teşekkür ederim ben her 5 thread sırası ile çalışıyor sandım, aynı anda çalışıyorlar demek çok teşekkür ederim kodları incleyeceğim çok şey öğreneceğim