Cara menggunakan threading di Python?

Saya mencoba untuk memahami threading di Python. I've melihat dokumentasi dan contoh-contoh, tetapi terus terang saja, banyak contoh-contoh yang terlalu canggih dan I'm mengalami kesulitan memahami mereka.

Bagaimana anda menunjukkan dengan jelas tugas-tugas yang dibagi untuk multi-threading?

Mengomentari pertanyaan (6)

Karena pertanyaan ini diajukan pada tahun 2010, telah ada penyederhanaan nyata dalam cara yang sangat sederhana multithreading dengan python dengan peta dan renang.

Kode di bawah ini berasal dari sebuah artikel/posting blog yang anda pasti harus check out (afiliasi) - Paralelisme dalam satu baris: Model yang lebih Baik untuk hari ke Hari Threading Tugas. I'll meringkas di bawah ini - itu akhirnya menjadi hanya beberapa baris kode:

from multiprocessing.dummy import Pool as ThreadPool 
pool = ThreadPool(4) 
results = pool.map(my_function, my_array)

Yang multithreaded versi:

results = []
for item in my_array:
    results.append(my_function(item))

Deskripsi

Peta adalah dingin sedikit fungsi, dan kunci untuk dengan mudah suntik paralelisme ke kode Python. Bagi mereka yang tidak terbiasa, peta adalah sesuatu yang diangkat dari bahasa-bahasa fungsional seperti Cadel. Ini adalah fungsi yang memetakan fungsi lain dari urutan.

Peta menangani iterasi urutan untuk kita, berlaku fungsi, dan toko-toko semua hasil dalam daftar berguna pada akhirnya.


Pelaksanaan

versi Paralel dari fungsi peta yang disediakan oleh dua perpustakaan:multiprocessing, dan juga sedikit diketahui, tapi sama-sama fantastis langkah anak:multiprocessing.dummy.

multiprocessing.dummy adalah persis sama seperti multiprocessing modul, tetapi menggunakan benang bukan (perbedaan penting - menggunakan beberapa proses untuk CPU-intensif tugas; benang untuk (dan selama) IO):

multiprocessing.dummy ulangan API dari multiprocessing tetapi tidak lebih dari bungkus sekitar threading modul.

import urllib2 
from multiprocessing.dummy import Pool as ThreadPool 

urls = [
  'http://www.python.org', 
  'http://www.python.org/about/',
  'http://www.onlamp.com/pub/a/python/2003/04/17/metaclasses.html',
  'http://www.python.org/doc/',
  'http://www.python.org/download/',
  'http://www.python.org/getit/',
  'http://www.python.org/community/',
  'https://wiki.python.org/moin/',
]

# make the Pool of workers
pool = ThreadPool(4) 

# open the urls in their own threads
# and return the results
results = pool.map(urllib2.urlopen, urls)

# close the pool and wait for the work to finish 
pool.close() 
pool.join() 

Dan waktu hasil:

Single thread:   14.4 seconds
       4 Pool:   3.1 seconds
       8 Pool:   1.4 seconds
      13 Pool:   1.3 seconds

Lewat beberapa argumen (karya-karya seperti ini hanya di Python 3.3 dan kemudian):

Untuk melewati beberapa array:

results = pool.starmap(function, zip(list_a, list_b))

atau untuk lulus konstan dan array:

results = pool.starmap(function, zip(itertools.repeat(constant), list_a))

Jika anda menggunakan versi sebelumnya dari Python, anda dapat melewati beberapa argumen melalui pemecahan masalah ini.

(Terima kasih kepada user136036 untuk membantu komentar)

Komentar (30)

Berikut ini's contoh sederhana: anda perlu mencoba beberapa alternatif Url dan kembali isi pertama untuk merespon.

import Queue
import threading
import urllib2

# called by each thread
def get_url(q, url):
    q.put(urllib2.urlopen(url).read())

theurls = ["http://google.com", "http://yahoo.com"]

q = Queue.Queue()

for u in theurls:
    t = threading.Thread(target=get_url, args = (q,u))
    t.daemon = True
    t.start()

s = q.get()
print s

Ini adalah kasus di mana threading digunakan sebagai optimasi sederhana: masing-masing subthread menunggu URL untuk mengatasi dan merespon, dalam rangka untuk menempatkan isinya pada antrian; setiap thread adalah sebuah daemon (won't menjaga proses sampai jika thread utama berakhir -- yang's lebih umum daripada tidak); thread utama dimulai subthreads, tidak mendapatkan pada antrian untuk menunggu sampai salah satu dari mereka telah melakukan menempatkan, kemudian memancarkan hasil dan berakhir (yang jatuh setiap subthreads yang mungkin masih bisa berjalan, karena mereka're daemon benang).

Penggunaan yang tepat dari benang dalam Python adalah selalu terhubung untuk operasi I/O (sejak CPython doesn't menggunakan beberapa core untuk menjalankan CPU-bound tugas-tugas pokoknya, satu-satunya alasan untuk threading tidak menghalangi proses sementara ada's menunggu untuk beberapa I/O). Antrian hampir selalu cara terbaik untuk pertanian bekerja untuk benang dan/atau mengumpulkan pekerjaan's hasil, by the way, dan mereka're intrinsik threadsafe sehingga mereka menyimpan anda dari khawatir tentang kunci, kondisi, peristiwa, semaphore, dan lain inter-thread koordinasi/komunikasi konsep.

Komentar (14)

CATATAN: sebenarnya paralelisasi dalam Python, anda harus menggunakan multiprocessing modul untuk membayar beberapa proses yang mengeksekusi secara paralel (karena global juru kunci, Python benang menyediakan interleaving tetapi pada kenyataannya dieksekusi secara bergantian, tidak secara paralel, dan hanya berguna ketika interleaving operasi I/O).

Namun, jika anda hanya mencari interleaving (atau melakukan operasi I/O yang dapat diparalelkan meskipun dunia juru kunci), maka threading modul adalah tempat untuk memulai. Sebagai contoh yang sangat sederhana, let's mempertimbangkan masalah menjumlahkan range yang besar dengan menjumlahkan subranges secara paralel:

import threading

class SummingThread(threading.Thread):
     def __init__(self,low,high):
         super(SummingThread, self).__init__()
         self.low=low
         self.high=high
         self.total=0

     def run(self):
         for i in range(self.low,self.high):
             self.total+=i

thread1 = SummingThread(0,500000)
thread2 = SummingThread(500000,1000000)
thread1.start() # This actually causes the thread to run
thread2.start()
thread1.join()  # This waits until the thread has completed
thread2.join()  
# At this point, both threads have completed
result = thread1.total + thread2.total
print result

Perhatikan bahwa di atas adalah sangat bodoh seperti itu tidak benar-benar tidak ada I/O dan akan dilaksanakan secara bergantian meskipun interleaved (dengan menambahkan overhead of context switching) di CPython karena global juru kunci.

Komentar (8)

Seperti yang lain disebutkan, CPython dapat menggunakan benang hanya untuk saya\O menunggu karena GIL. Jika anda ingin mendapatkan keuntungan dari beberapa core CPU-bound tugas-tugas, menggunakan multiprocessing:

from multiprocessing import Process

def f(name):
    print 'hello', name

if __name__ == '__main__':
    p = Process(target=f, args=('bob',))
    p.start()
    p.join()
Komentar (5)

Sekedar catatan, Antrian tidak diperlukan untuk threading.

Ini adalah contoh paling sederhana yang saya bisa membayangkan bahwa menunjukkan 10 proses yang berjalan secara bersamaan.

import threading
from random import randint
from time import sleep

def print_number(number):
    # Sleeps a random 1 to 10 seconds
    rand_int_var = randint(1, 10)
    sleep(rand_int_var)
    print "Thread " + str(number) + " slept for " + str(rand_int_var) + " seconds"

thread_list = []

for i in range(1, 10):
    # Instantiates the thread
    # (i) does not make a sequence, so (i,)
    t = threading.Thread(target=print_number, args=(i,))
    # Sticks the thread in a list so that it remains accessible
    thread_list.append(t)

# Starts threads
for thread in thread_list:
    thread.start()

# This blocks the calling thread until the thread whose join() method is called is terminated.
# From http://docs.python.org/2/library/threading.html#thread-objects
for thread in thread_list:
    thread.join()

# Demonstrates that the main process waited for threads to complete
print "Done"
Komentar (5)

Jawaban dari Alex Martelli membantu saya, namun di sini adalah versi modifikasi yang saya pikir itu lebih berguna (setidaknya untuk saya).

Diperbarui: bekerja di kedua python2 dan python3

try:
    # for python3
    import queue
    from urllib.request import urlopen
except:
    # for python2 
    import Queue as queue
    from urllib2 import urlopen

import threading

worker_data = ['http://google.com', 'http://yahoo.com', 'http://bing.com']

#load up a queue with your data, this will handle locking
q = queue.Queue()
for url in worker_data:
    q.put(url)

#define a worker function
def worker(url_queue):
    queue_full = True
    while queue_full:
        try:
            #get your data off the queue, and do some work
            url = url_queue.get(False)
            data = urlopen(url).read()
            print(len(data))

        except queue.Empty:
            queue_full = False

#create as many threads as you want
thread_count = 5
for i in range(thread_count):
    t = threading.Thread(target=worker, args = (q,))
    t.start()
Komentar (6)

Saya menemukan ini sangat berguna: membuat sebagai banyak benang sebagai core dan membiarkan mereka melaksanakan (besar) jumlah dari tugas-tugas (dalam hal ini, memanggil sebuah program shell):

import Queue
import threading
import multiprocessing
import subprocess

q = Queue.Queue()
for i in range(30): #put 30 tasks in the queue
    q.put(i)

def worker():
    while True:
        item = q.get()
        #execute a task: call a shell program and wait until it completes
        subprocess.call("echo "+str(item), shell=True) 
        q.task_done()

cpus=multiprocessing.cpu_count() #detect number of cores
print("Creating %d threads" % cpus)
for i in range(cpus):
     t = threading.Thread(target=worker)
     t.daemon = True
     t.start()

q.join() #block until all tasks are done
Komentar (3)

Diberikan sebuah fungsi, f, thread seperti ini:

import threading
threading.Thread(target=f).start()

Untuk melewati argumen untuk f

threading.Thread(target=f, args=(a,b,c)).start()
Komentar (5)

Python 3 memiliki fasilitas Launching tugas-tugas paralel. Hal ini membuat pekerjaan kami lebih mudah.

Itu untuk thread pooling dan Proses pooling.

Berikut memberikan wawasan:

ThreadPoolExecutor Contoh

import concurrent.futures
import urllib.request

URLS = ['http://www.foxnews.com/',
        'http://www.cnn.com/',
        'http://europe.wsj.com/',
        'http://www.bbc.co.uk/',
        'http://some-made-up-domain.com/']

# Retrieve a single page and report the URL and contents
def load_url(url, timeout):
    with urllib.request.urlopen(url, timeout=timeout) as conn:
        return conn.read()

# We can use a with statement to ensure threads are cleaned up promptly
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
    # Start the load operations and mark each future with its URL
    future_to_url = {executor.submit(load_url, url, 60): url for url in URLS}
    for future in concurrent.futures.as_completed(future_to_url):
        url = future_to_url[future]
        try:
            data = future.result()
        except Exception as exc:
            print('%r generated an exception: %s' % (url, exc))
        else:
            print('%r page is %d bytes' % (url, len(data)))

ProcessPoolExecutor

import concurrent.futures
import math

PRIMES = [
    112272535095293,
    112582705942171,
    112272535095293,
    115280095190773,
    115797848077099,
    1099726899285419]

def is_prime(n):
    if n % 2 == 0:
        return False

    sqrt_n = int(math.floor(math.sqrt(n)))
    for i in range(3, sqrt_n + 1, 2):
        if n % i == 0:
            return False
    return True

def main():
    with concurrent.futures.ProcessPoolExecutor() as executor:
        for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)):
            print('%d is prime: %s' % (number, prime))

if __name__ == '__main__':
    main()
Komentar (0)

Bagi saya, contoh yang sempurna untuk Threading adalah pemantauan peristiwa Asinkron. Terlihat pada kode ini.

# thread_test.py
import threading
import time 

class Monitor(threading.Thread):
    def __init__(self, mon):
        threading.Thread.__init__(self)
        self.mon = mon

    def run(self):
        while True:
            if self.mon[0] == 2:
                print "Mon = 2"
                self.mon[0] = 3;

Anda dapat bermain dengan kode ini dengan membuka IPython sesi dan melakukan sesuatu seperti:

>>>from thread_test import Monitor
>>>a = [0]
>>>mon = Monitor(a)
>>>mon.start()
>>>a[0] = 2
Mon = 2
>>>a[0] = 2
Mon = 2

Tunggu beberapa menit

>>>a[0] = 2
Mon = 2
Komentar (5)

Menggunakan baru menyala bersamaan.kontrak modul

def sqr(val):
    import time
    time.sleep(0.1)
    return val * val

def process_result(result):
    print(result)

def process_these_asap(tasks):
    import concurrent.futures

    with concurrent.futures.ProcessPoolExecutor() as executor:
        futures = []
        for task in tasks:
            futures.append(executor.submit(sqr, task))

        for future in concurrent.futures.as_completed(futures):
            process_result(future.result())
        # Or instead of all this just do:
        # results = executor.map(sqr, tasks)
        # list(map(process_result, results))

def main():
    tasks = list(range(10))
    print('Processing {} tasks'.format(len(tasks)))
    process_these_asap(tasks)
    print('Done')
    return 0

if __name__ == '__main__':
    import sys
    sys.exit(main())

Pelaksana pendekatan mungkin tampak akrab bagi semua orang yang mendapatkan tangan mereka kotor dengan Java sebelumnya.

Juga di samping catatan: Untuk menjaga alam semesta waras, don't lupa untuk menutup kolam renang/pelaksana jika anda don't menggunakan dengan konteks (yang begitu mengagumkan bahwa ia melakukannya untuk anda)

Komentar (0)

Paling dokumentasi dan tutorial menggunakan Python's Threading dan Antrian modul mereka bisa tampak luar biasa untuk pemula.

Mungkin mempertimbangkan bersamaan.berjangka.ThreadPoolExecutor modul python 3. Dikombinasikan dengan dengan klausul dan daftar pemahaman itu bisa menjadi nyata pesona.

from concurrent.futures import ThreadPoolExecutor, as_completed

def get_url(url):
    # Your actual program here. Using threading.Lock() if necessary
    return ""

# List of urls to fetch
urls = ["url1", "url2"]

with ThreadPoolExecutor(max_workers = 5) as executor:

    # Create threads 
    futures = {executor.submit(get_url, url) for url in urls}

    # as_completed() gives you the threads once finished
    for f in as_completed(futures):
        # Get the results 
        rs = f.result()
Komentar (0)

Saya melihat banyak contoh di sini di mana tidak ada kerja nyata sedang dilakukan + mereka sebagian besar CPU bound. Berikut adalah contoh sebuah CPU terikat tugas yang menghitung semua bilangan prima antara 10 juta dan 10,05 juta. Saya telah menggunakan semua 4 metode berikut

import math
import timeit
import threading
import multiprocessing
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor

def time_stuff(fn):
    """
    Measure time of execution of a function
    """
    def wrapper(*args, **kwargs):
        t0 = timeit.default_timer()
        fn(*args, **kwargs)
        t1 = timeit.default_timer()
        print("{} seconds".format(t1 - t0))
    return wrapper

def find_primes_in(nmin, nmax):
    """
    Compute a list of prime numbers between the given minimum and maximum arguments
    """
    primes = []

    #Loop from minimum to maximum
    for current in range(nmin, nmax + 1):

        #Take the square root of the current number
        sqrt_n = int(math.sqrt(current))
        found = False

        #Check if the any number from 2 to the square root + 1 divides the current numnber under consideration
        for number in range(2, sqrt_n + 1):

            #If divisible we have found a factor, hence this is not a prime number, lets move to the next one
            if current % number == 0:
                found = True
                break

        #If not divisible, add this number to the list of primes that we have found so far
        if not found:
            primes.append(current)

    #I am merely printing the length of the array containing all the primes but feel free to do what you want
    print(len(primes))

@time_stuff
def sequential_prime_finder(nmin, nmax):
    """
    Use the main process and main thread to compute everything in this case
    """
    find_primes_in(nmin, nmax)

@time_stuff
def threading_prime_finder(nmin, nmax):
    """
    If the minimum is 1000 and the maximum is 2000 and we have 4 workers
    1000 - 1250 to worker 1
    1250 - 1500 to worker 2
    1500 - 1750 to worker 3
    1750 - 2000 to worker 4
    so lets split the min and max values according to the number of workers
    """
    nrange = nmax - nmin
    threads = []
    for i in range(8):
        start = int(nmin + i * nrange/8)
        end = int(nmin + (i + 1) * nrange/8)

        #Start the thrread with the min and max split up to compute
        #Parallel computation will not work here due to GIL since this is a CPU bound task
        t = threading.Thread(target = find_primes_in, args = (start, end))
        threads.append(t)
        t.start()

    #Dont forget to wait for the threads to finish
    for t in threads:
        t.join()

@time_stuff
def processing_prime_finder(nmin, nmax):
    """
    Split the min, max interval similar to the threading method above but use processes this time
    """
    nrange = nmax - nmin
    processes = []
    for i in range(8):
        start = int(nmin + i * nrange/8)
        end = int(nmin + (i + 1) * nrange/8)
        p = multiprocessing.Process(target = find_primes_in, args = (start, end))
        processes.append(p)
        p.start()

    for p in processes:
        p.join()

@time_stuff
def thread_executor_prime_finder(nmin, nmax):
    """
    Split the min max interval similar to the threading method but use thread pool executor this time
    This method is slightly faster than using pure threading as the pools manage threads more efficiently
    This method is still slow due to the GIL limitations since we are doing a CPU bound task
    """
    nrange = nmax - nmin
    with ThreadPoolExecutor(max_workers = 8) as e:
        for i in range(8):
            start = int(nmin + i * nrange/8)
            end = int(nmin + (i + 1) * nrange/8)
            e.submit(find_primes_in, start, end)

@time_stuff
def process_executor_prime_finder(nmin, nmax):
    """
    Split the min max interval similar to the threading method but use the process pool executor
    This is the fastest method recorded so far as it manages process efficiently + overcomes GIL limitations
    RECOMMENDED METHOD FOR CPU BOUND TASKS
    """
    nrange = nmax - nmin
    with ProcessPoolExecutor(max_workers = 8) as e:
        for i in range(8):
            start = int(nmin + i * nrange/8)
            end = int(nmin + (i + 1) * nrange/8)
            e.submit(find_primes_in, start, end)

def main():
    nmin = int(1e7)
    nmax = int(1.05e7)
    print("Sequential Prime Finder Starting")
    sequential_prime_finder(nmin, nmax)
    print("Threading Prime Finder Starting")
    threading_prime_finder(nmin, nmax)
    print("Processing Prime Finder Starting")
    processing_prime_finder(nmin, nmax)
    print("Thread Executor Prime Finder Starting")
    thread_executor_prime_finder(nmin, nmax)
    print("Process Executor Finder Starting")
    process_executor_prime_finder(nmin, nmax)

main()

Berikut ini adalah hasil on my Mac OSX 4 inti mesin

Sequential Prime Finder Starting
9.708213827005238 seconds
Threading Prime Finder Starting
9.81836523200036 seconds
Processing Prime Finder Starting
3.2467174359990167 seconds
Thread Executor Prime Finder Starting
10.228896902000997 seconds
Process Executor Finder Starting
2.656402041000547 seconds
Komentar (4)

Berikut ini adalah contoh yang sangat sederhana dari impor CSV menggunakan threading. [Perpustakaan inklusi mungkin berbeda untuk tujuan yang berbeda ]

Fungsi Pembantu:

from threading import Thread
from project import app 
import csv

def import_handler(csv_file_name):
    thr = Thread(target=dump_async_csv_data, args=[csv_file_name])
    thr.start()

def dump_async_csv_data(csv_file_name):
    with app.app_context():
        with open(csv_file_name) as File:
            reader = csv.DictReader(File)
            for row in reader:
                #DB operation/query

Driver Fungsi:

import_handler(csv_file_name) 
Komentar (0)

Multi-threading dengan contoh sederhana yang akan membantu. Anda dapat menjalankan dan memahami dengan mudah bagaimana multi thread yang bekerja di python. Aku kunci yang digunakan untuk mencegah akses thread lain sampai sebelumnya benang selesai pekerjaan mereka. Dengan menggunakan

tLock = threading.BoundedSemaphore(nilai=4)

baris kode ini anda dapat memungkinkan jumlah proses pada suatu waktu dan tetap memegang untuk sisa benang yang akan berjalan nanti atau setelah selesai proses-proses yang terdahulu.

import threading
import time

#tLock = threading.Lock()
tLock = threading.BoundedSemaphore(value=4)
def timer(name, delay, repeat):
    print  "\r\nTimer: ", name, " Started"
    tLock.acquire()
    print "\r\n", name, " has the acquired the lock"
    while repeat > 0:
        time.sleep(delay)
        print "\r\n", name, ": ", str(time.ctime(time.time()))
        repeat -= 1

    print "\r\n", name, " is releaseing the lock"
    tLock.release()
    print "\r\nTimer: ", name, " Completed"

def Main():
    t1 = threading.Thread(target=timer, args=("Timer1", 2, 5))
    t2 = threading.Thread(target=timer, args=("Timer2", 3, 5))
    t3 = threading.Thread(target=timer, args=("Timer3", 4, 5))
    t4 = threading.Thread(target=timer, args=("Timer4", 5, 5))
    t5 = threading.Thread(target=timer, args=("Timer5", 0.1, 5))

    t1.start()
    t2.start()
    t3.start()
    t4.start()
    t5.start()

    print "\r\nMain Complete"

if __name__ == "__main__":
    Main()
Komentar (0)

Tidak ada solusi di atas benar-benar menggunakan beberapa core pada GNU/Linux server (di mana saya don't memiliki hak admin). Mereka hanya berlari pada satu inti. Aku digunakan tingkat yang lebih rendah os.garpu antarmuka untuk menelurkan beberapa proses. Ini adalah kode yang bekerja untuk saya:

from os import fork

values = ['different', 'values', 'for', 'threads']

for i in range(len(values)):
    p = fork()
    if p == 0:
        my_function(values[i])
        break
Komentar (0)

Saya ingin berkontribusi dengan contoh sederhana dan penjelasan-penjelasan saya've ditemukan berguna ketika saya harus mengatasi masalah ini sendiri.

Dalam jawaban ini anda akan menemukan beberapa informasi tentang Python's GIL (Global Juru Kunci) dan sederhana sehari-hari contoh yang ditulis menggunakan multiprocessing.dummy ditambah beberapa tolok ukur sederhana.

Global Juru Kunci (GIL)

Python doesn't memungkinkan multi-threading dalam arti sebenarnya dari kata itu. Memiliki multi-threading paket tetapi jika anda ingin untuk multi-thread untuk kecepatan kode anda, maka itu's biasanya bukan ide yang baik untuk menggunakannya. Python memiliki konstruk yang disebut Global Juru Kunci (GIL). GIL memastikan bahwa hanya salah satu dari anda 'benang' dapat dieksekusi pada satu waktu. Thread memperoleh GIL, tidak sedikit bekerja, kemudian melewati GIL ke thread berikutnya. Ini terjadi sangat cepat sehingga mata manusia mungkin tampak seperti benang mengeksekusi secara paralel, tapi mereka benar-benar hanya bergiliran menggunakan CPU core. Semua ini GIL lewat menambahkan overhead untuk eksekusi. Ini berarti bahwa jika anda ingin membuat kode anda berjalan lebih cepat kemudian menggunakan threading paket sering isn't ide yang baik.

Ada alasan untuk menggunakan Python's threading paket. Jika anda ingin menjalankan beberapa hal secara bersamaan, dan efisiensi yang tidak perhatian, maka itu's benar-benar baik dan nyaman. Atau jika anda menjalankan kode yang diperlukan untuk menunggu sesuatu (seperti beberapa IO) maka itu bisa membuat banyak akal. Tapi threading perpustakaan won't membiarkan anda menggunakan ekstra core CPU.

Multi-threading dapat di-outsource untuk sistem operasi (dengan melakukan multi-processing), beberapa aplikasi eksternal yang memanggil anda kode Python (misalnya, Percikan atau Hadoop), atau beberapa kode yang anda Python kode panggilan (misalnya: anda bisa memiliki anda Python code memanggil fungsi C yang tidak mahal multi-threaded barang-barang).

Mengapa Hal Ini Penting

Karena banyak orang-orang menghabiskan banyak waktu mencoba untuk menemukan kemacetan di mewah mereka Python multi-threaded kode sebelum mereka belajar apa GIL.

Setelah informasi ini jelas di sini's my kode:

#!/bin/python
from multiprocessing.dummy import Pool
from subprocess import PIPE,Popen
import time
import os

# In the variable pool_size we define the "parallelness".
# For CPU-bound tasks, it doesn't make sense to create more Pool processes
# than you have cores to run them on.
#
# On the other hand, if you are using I/O-bound tasks, it may make sense
# to create a quite a few more Pool processes than cores, since the processes
# will probably spend most their time blocked (waiting for I/O to complete).
pool_size = 8

def do_ping(ip):
    if os.name == 'nt':
        print ("Using Windows Ping to " + ip)
        proc = Popen(['ping', ip], stdout=PIPE)
        return proc.communicate()[0]
    else:
        print ("Using Linux / Unix Ping to " + ip)
        proc = Popen(['ping', ip, '-c', '4'], stdout=PIPE)
        return proc.communicate()[0]

os.system('cls' if os.name=='nt' else 'clear')
print ("Running using threads\n")
start_time = time.time()
pool = Pool(pool_size)
website_names = ["www.google.com","www.facebook.com","www.pinterest.com","www.microsoft.com"]
result = {}
for website_name in website_names:
    result[website_name] = pool.apply_async(do_ping, args=(website_name,))
pool.close()
pool.join()
print ("\n--- Execution took {} seconds ---".format((time.time() - start_time)))

# Now we do the same without threading, just to compare time
print ("\nRunning NOT using threads\n")
start_time = time.time()
for website_name in website_names:
    do_ping(website_name)
print ("\n--- Execution took {} seconds ---".format((time.time() - start_time)))

# Here's one way to print the final output from the threads
output = {}
for key, value in result.items():
    output[key] = value.get()
print ("\nOutput aggregated in a Dictionary:")
print (output)
print ("\n")

print ("\nPretty printed output:")
for key, value in output.items():
    print (key + "\n")
    print (value)
Komentar (0)

Dengan pinjaman dari post ini kita tahu tentang memilih antara multithreading, multiprocessing, dan async dan penggunaan mereka.

Python3 memiliki built-in perpustakaan dalam rangka untuk concurrency dan paralelisme: bersamaan.kontrak

Jadi saya menunjukkan dengan percobaan untuk menjalankan empat tugas (yaitu .tidur() metode) oleh Threading-Renang dengan cara:

from concurrent.futures import ThreadPoolExecutor, as_completed
from time import sleep, time

def concurrent(max_worker=1):
    futures = []

    tick = time()
    with ThreadPoolExecutor(max_workers=max_worker) as executor:
        futures.append(executor.submit(sleep, 2))
        futures.append(executor.submit(sleep, 1))
        futures.append(executor.submit(sleep, 7))
        futures.append(executor.submit(sleep, 3))

        for future in as_completed(futures):
            if future.result() is not None:
                print(future.result())

    print('Total elapsed time by {} workers:'.format(max_worker), time()-tick)

concurrent(5)
concurrent(4)
concurrent(3)
concurrent(2)
concurrent(1)

Keluar:

Total elapsed time by 5 workers: 7.007831811904907
Total elapsed time by 4 workers: 7.007944107055664
Total elapsed time by 3 workers: 7.003149509429932
Total elapsed time by 2 workers: 8.004627466201782
Total elapsed time by 1 workers: 13.013478994369507

[CATATAN]:

  • Seperti yang anda lihat pada hasil di atas, kasus terbaik adalah 3 pekerja untuk empat tugas.
  • Jika anda memiliki tugas proses sebaliknya dari I/O bound (menggunakan thread) anda bisa mengubah ThreadPoolExecutor dengan ProcessPoolExecutor
Komentar (0)
import threading
import requests

def send():

  r = requests.get('https://www.stackoverlow.com')

thread = []
t = threading.Thread(target=send())
thread.append(t)
t.start()
Komentar (5)