Как использовать потоки в Python?

Я пытаюсь понять потоки в Python. Я просмотрел документацию и примеры, но, честно говоря, многие примеры слишком сложны, и мне трудно понять их.

Как вы четко показываете разделяемые задачи для многопоточности?

Ответы

Ответ 1

С тех пор, как этот вопрос был задан в 2010 году, произошло реальное упрощение в том, как сделать простую многопоточность с python с map и pool.

Приведенный ниже код взят из статьи/поста в блоге, который вы обязательно должны проверить (без принадлежности) - Параллелизм в одной строке: лучшая модель для повседневных задач многопоточности. Я подведу итог ниже - это всего лишь несколько строк кода:

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

Какая многопоточная версия:

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

Описание

Map - маленькая классная функция, и ключ к легкому внедрению параллелизма в ваш код Python. Для тех, кто незнаком, map - это нечто, взятое из функциональных языков, таких как Lisp. Это функция, которая отображает другую функцию в последовательности.

Map обрабатывает для нас итерации последовательности, применяет функцию и в конце сохраняет все результаты в удобном списке.

enter image description here


Реализация

Параллельные версии функции map предоставляются двумя библиотеками: multiprocessing, а также ее малоизвестным, но не менее фантастическим дочерним элементом: multiprocessing.dummy.

multiprocessing.dummy - это то же самое, что и многопроцессорный модуль, но вместо него используются потоки (важное различие - используйте несколько процессов для задач, интенсивно использующих процессор; потоки для (и во время) ввода-вывода):

multiprocessing.dummy копирует API многопроцессорной обработки, но является не более чем оболочкой для модуля потоков.

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() 

И сроки результатов:

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

Передача нескольких аргументов (работает так только в Python 3.3 и более поздних версиях):

Чтобы передать несколько массивов:

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

или передать константу и массив:

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

Если вы используете более раннюю версию Python, вы можете передать несколько аргументов через этот обходной путь.

(Спасибо user136036 за полезный комментарий)

Ответ 2

Вот простой пример: вам нужно попробовать несколько альтернативных URL-адресов и вернуть содержимое первого для ответа.

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

Это случай, когда потоки используются как простая оптимизация: каждый подпроцесс ожидает, когда URL-адрес будет разрешаться и отвечать, чтобы помещать его содержимое в очередь; каждый поток - демон (не будет продолжать процесс, если конец основного потока - это более общий, чем нет); основной поток запускает все субтитры, делает ли get в очереди ждать, пока один из них выполнит put, затем испустит результаты и завершит (что приведет к удалению любых подпрограмм, которые все еще могут выполняться, поскольку они демона).

Правильное использование потоков в Python неизменно связано с операциями ввода-вывода (поскольку CPython не использует несколько ядер для выполнения задач с привязкой к процессору в любом случае, единственная причина потоковой передачи - это не блокирование процесса, в то время как есть ожидание некоторых I/O). Очереди - это, почти всегда, лучший способ обработать работу с потоками и/или собирать результаты работы, между прочим, и они по сути являются потокобезопасными, поэтому они избавляют вас от беспокойства о блокировках, условиях, событиях, семафорах и других интер- концепции координации/коммуникации потоков.

Ответ 3

ПРИМЕЧАНИЕ. Для фактической распараллеливания в Python вы должны использовать модуль multiprocessing для развертывания нескольких процессов, которые выполняются параллельно (из-за блокировки глобального интерпретатора потоки Python обеспечивают чередование, но на самом деле выполняются серийно, а не параллельно, и полезны только при чередовании операций ввода-вывода).

Однако, если вы просто ищете чередование (или выполняете операции ввода-вывода, которые можно распараллелить, несмотря на блокировку глобального интерпретатора), тогда threading - это место для запуска. В качестве действительно простого примера рассмотрим задачу суммирования большого диапазона путем суммирования поддиапазонов параллельно:

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

Обратите внимание, что приведенное выше является очень глупым примером, поскольку он не имеет абсолютно никакого ввода-вывода и будет выполняться последовательно, хотя и чередоваться (с добавленными издержками переключения контекста) в CPython из-за блокировки глобального интерпретатора.

Ответ 4

Как и другие, CPython может использовать потоки только для ожиданий I\O из-за GIL. Если вы хотите использовать несколько ядер для задач, связанных с CPU, используйте multiprocessing:

from multiprocessing import Process

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

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

Ответ 5

Просто примечание: для потоковой передачи не требуется очередь.

Это самый простой пример, который я мог представить, который показывает 10 процессов, работающих одновременно.

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"

Ответ 6

Ответ от Алекса Мартелли помог мне, однако здесь есть измененная версия, которая, на мой взгляд, была более полезной (по крайней мере для меня).

Обновлено: работает как в python2, так и в 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()

Ответ 7

Я нашел это очень полезным: создайте столько потоков, сколько ядер, и позвольте им выполнить (большое) количество задач (в этом случае вызывать программу оболочки):

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

Ответ 8

Для функции f выполните ее следующим образом:

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

Чтобы передать аргументы f

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

Ответ 9

Python 3 имеет возможность Запуск параллельных задач. Это облегчает нашу работу.

Он имеет объединение потоков и Пул процессов.

Следующее дает представление:

Пример ThreadPoolExecutor

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()

Ответ 10

Для меня идеальным примером Threading является мониторинг асинхронных событий. Посмотрите на этот код.

# 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;

Вы можете играть с этим кодом, открыв сеанс IPython и сделав что-то вроде:

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

Подождите несколько минут

>>>a[0] = 2
Mon = 2

Ответ 11

Использование нового нового concurrent.futures

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())

Подход исполнителя может показаться знакомым всем тем, кто раньше испарился перед Java.

Также на стороне примечания: Чтобы сохранить вселенную в здравом уме, не забудьте закрыть ваши пулы/исполнители, если вы не используете контекст with (который настолько огромен, что он делает это для вас)

Ответ 12

Большинство документов и руководств используют модуль Python Threading и Queue может показаться подавляющим для новичков.

Возможно рассмотреть concurrent.futures.ThreadPoolExecutor модуль питона 3. В сочетании с with п и список пониманием, это может быть реальным очарованием.

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()

Ответ 13

Я видел здесь много примеров, где не выполнялась настоящая работа + они были главным образом связаны с процессором. Ниже приведен пример задачи, связанной с процессором, которая вычисляет все простые числа от 10 миллионов до 10,05 миллионов. Я использовал все 4 метода здесь

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()

Вот результаты на моей основной машине Mac OSX 4

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

Ответ 14

Вот простой пример импорта CSV с использованием потоковой обработки. [Включение библиотеки может отличаться для разных целей]

Функции помощника:

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

Функция драйвера:

import_handler(csv_file_name) 

Ответ 15

Многопоточность с простым примером, который будет полезен. Вы можете запустить его и легко понять, как работает многопоточный поток на python. Я использовал блокировку для предотвращения доступа к другому потоку, пока предыдущие потоки не завершили свою работу. Используя

tLock = threading.BoundedSemaphore(value = 4)

эту строку кода вы можете разрешить количество процессов за один раз и удерживать остальную часть потока, которая будет работать позже или после завершения предыдущих процессов.

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()

Ответ 16

Наряду со всеми замечательными ответами и примерами здесь, в стеке, которые помогли мне лично понять вышеупомянутую многопроцессорность и потоки, следующий сайт (здесь я предоставил ссылки на конкретные темы из-за простых примеров, содержащихся в нем; op запрошен.), действительно нажал для меня, с его документацией и моим пониманием любых вопросов, которые у меня были о питоне до сих пор, она надеется, что она может помочь кому-то здесь столько, сколько я.

  • Нет аффилиации

Python Threading

Многопроцессорность Python

Пока я узнаю множество ответов, я считаю, что было бы полезно, если я смогу помочь другому лучше понять что-то в их интересах .

Ответ 17

Ни одно из вышеперечисленных решений фактически не использовало несколько ядер на моем сервере GNU/Linux (где у меня нет прав администратора). Они просто бежали по одному ядру. Я использовал интерфейс os.fork более низкого уровня для os.fork нескольких процессов. Это код, который работал для меня:

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

Ответ 18

Я хотел бы поделиться простым примером и объяснениями, которые я нашел полезными, когда мне пришлось самому заняться этой проблемой.

В этом ответе вы найдете некоторую информацию о Python GIL (Global Interpreter Lock) и простой пример из повседневной жизни, написанный с использованием multiprocessing.dummy, а также несколько простых тестов.

Глобальная блокировка интерпретатора (GIL)

Python не допускает многопоточность в прямом смысле этого слова. Имеет многопоточный пакет но если вы хотите многопоточность, чтобы ускорить ваш код, то его использование обычно не очень хорошая идея. Python имеет конструкцию, называемую Global Interpreter Lock (GIL). GIL гарантирует, что только один из ваших "потоков" может выполняться одновременно. Поток получает GIL, выполняет небольшую работу, а затем передает GIL следующему потоку. Это происходит очень быстро, поэтому человеческому глазу может показаться, что ваши потоки выполняются параллельно, но они на самом деле просто по очереди используют одно и то же ядро процессора. Вся эта передача GIL увеличивает накладные расходы на выполнение. Это означает, что если вы хотите, чтобы ваш код работал быстрее, чем использовать многопоточность пакет часто не очень хорошая идея.

Есть причины использовать пакет потоков Python. Если вы хотите запустить некоторые вещи одновременно, и эффективность не является проблемой, тогда это совершенно нормально и удобно. Или, если вы запускаете код, который должен чего-то ждать (например, какой-нибудь ввод-вывод), тогда это может иметь большой смысл. Но библиотека потоков не позволит вам использовать дополнительные ядра процессора.

Многопоточность может быть передана на аутсорсинг операционной системе (с помощью многопоточности) какое-то внешнее приложение, которое вызывает ваш код Python (например, Spark или Hadoop), или некоторый код, который ваш Python вызовы кода (например, ваш код Python может вызывать функцию C, которая выполняет дорогостоящие многопоточные операции).

Почему это важно

Потому что много людей проводят много времени, пытаясь найти узкие места в своей фантазии Многопоточный код Python, прежде чем они узнают, что такое GIL.

Как только эта информация станет понятна, мой код:

#!/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 does not 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 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)

Ответ 19

import threading   
myHeavyFctThread = threading.Thread(name='myHeavyFunction', target=myHeavyFunction)
f = threading.Thread(name='foreground', target=foreground)

когда вместо myHeavyFunction вы передаете имя fct и когда вам нужно активировать поток:

myHeavyFctThread.start()

Я знаю, что уже поздно, но может кому-то помочь: D

Ответ 20

import threading
import requests

def send():

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

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

Ответ 21

С заимствованиями из этого поста мы узнаем о выборе между многопоточностью, многопроцессорностью и асинхронностью и их использованием.

В Python3 есть новая встроенная библиотека для параллелизма и параллелизма: concurrent.futures

Итак, я продемонстрировал экспериментом выполнение четырех задач (т.е. метод .sleep()) способом Threading-Pool:

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)

Out:

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

[Примечание]:

  • Как видно из приведенных выше результатов, лучшим примером были 3 работники для выполнения этих четырех задач.
  • Если у вас есть задача процесса вместо привязки ввода/вывода (с использованием thread), вы можете изменить ThreadPoolExecutor с помощью ProcessPoolExecutor

Ответ 22

Здесь args является кортежем аргументов; используйте пустой кортеж для вызова функции без передачи каких-либо аргументов. kwargs - необязательный словарь аргументов ключевых слов.

Пример

#!/usr/bin/python

import thread
import time

# Define a function for the thread
def print_time( threadName, delay):
   count = 0
   while count < 5:
      time.sleep(delay)
      count += 1
      print "%s: %s" % ( threadName, time.ctime(time.time()) )

# Create two threads as follows
try:
   thread.start_new_thread( print_time, ("Thread-1", 2, ) )
   thread.start_new_thread( print_time, ("Thread-2", 4, ) )
except:
   print "Error: unable to start thread"

while 1:
   pass

При выполнении вышеуказанного кода он производит следующий результат:

Thread-1: Thu Jan 22 15:42:17 2009
Thread-1: Thu Jan 22 15:42:19 2009
Thread-2: Thu Jan 22 15:42:19 2009
Thread-1: Thu Jan 22 15:42:21 2009
Thread-2: Thu Jan 22 15:42:23 2009
Thread-1: Thu Jan 22 15:42:23 2009
Thread-1: Thu Jan 22 15:42:25 2009
Thread-2: Thu Jan 22 15:42:27 2009
Thread-2: Thu Jan 22 15:42:31 2009
Thread-2: Thu Jan 22 15:42:35 2009