Создание потоков в Python

177

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

Пример кода, который я посмотрел:

import threading

def MyThread (threading.thread):
    # doing something........

def MyThread2 (threading.thread):
    # doing something........

MyThread().start()
MyThread2().start()

У меня проблемы с получением этой работы. Я бы предпочел, чтобы это происходило с использованием многопоточной функции, а не класса.

Это рабочий скрипт:

from threading import Thread

class myClass():

    def help(self):
        os.system('./ssh.py')

    def nope(self):
        a = [1,2,3,4,5,6,67,78]
        for i in a:
            print i
            sleep(1)


if __name__ == "__main__":
    Yep = myClass()
    thread = Thread(target = Yep.help)
    thread2 = Thread(target = Yep.nope)
    thread.start()
    thread2.start()
    thread.join()
    print 'Finished'
chrissygormley
источник

Ответы:

323

Вам не нужно использовать подкласс Threadдля этой работы - взгляните на простой пример, который я публикую ниже, чтобы увидеть, как:

from threading import Thread
from time import sleep

def threaded_function(arg):
    for i in range(arg):
        print("running")
        sleep(1)


if __name__ == "__main__":
    thread = Thread(target = threaded_function, args = (10, ))
    thread.start()
    thread.join()
    print("thread finished...exiting")

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

JKP
источник
Я попробовал это. Я добавил скрипт выше. Не могли бы вы рассказать мне, как запустить вторую функцию рядом с первой? Спасибо
chrissygormley
6
@chrissygormley: блоки join () до завершения первого потока.
FogleBird
4
@chrissygormley: как уже упоминалось, объединяйте блоки до тех пор, пока не завершится поток, к которому вы присоединяетесь, поэтому в вашем случае запустите второй поток с вашей второй функцией в качестве цели для одновременного выполнения двух функций, а затем, при необходимости, присоедините одну из них, если Вы просто хотите подождать, пока они не будут сделаны.
2009 года
41
Я продолжал читать exitingкак exciting, что я все равно считал более подходящим.
Чейз Робертс
42

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

def MyThread ( threading.thread ):
  • Вы не можете создать подкласс с функцией; только с классом
  • Если бы вы собирались использовать подкласс, вы хотели бы использовать потоки. Тема, а не потоки.

Если вы действительно хотите сделать это только с функциями, у вас есть два варианта:

С резьбой:

import threading
def MyThread1():
    pass
def MyThread2():
    pass

t1 = threading.Thread(target=MyThread1, args=[])
t2 = threading.Thread(target=MyThread2, args=[])
t1.start()
t2.start()

С резьбой:

import thread
def MyThread1():
    pass
def MyThread2():
    pass

thread.start_new_thread(MyThread1, ())
thread.start_new_thread(MyThread2, ())

Документ для thread.start_new_thread

Jorenko
источник
2
Второй аргумент должен быть кортежем дляthread.start_new_thread(function, args[, kwargs])
venkatvb
13

Я попытался добавить еще один join (), и, похоже, сработало. Вот код

from threading import Thread
from time import sleep

def function01(arg,name):
    for i in range(arg):
        print(name,'i---->',i,'\n')
        print (name,"arg---->",arg,'\n')
        sleep(1)

def test01():
    thread1 = Thread(target = function01, args = (10,'thread1', ))
    thread1.start()
    thread2 = Thread(target = function01, args = (10,'thread2', ))
    thread2.start()
    thread1.join()
    thread2.join()
    print ("thread finished...exiting")

test01()
GGG
источник
3

Вы можете использовать targetаргумент в Threadконструкторе для прямой передачи функции, которая вызывается вместо run.

unholysampler
источник
2

Вы переопределили метод run ()? Если вы переопределили __init__, вы обязательно позвоните в базу threading.Thread.__init__()?

После запуска двух потоков основной поток продолжает бесконечно выполнять работу / блокировать / объединять дочерние потоки, чтобы выполнение основного потока не завершалось до того, как дочерние потоки завершат выполнение своих задач?

И, наконец, вы получаете какие-то необработанные исключения?

Джереми Браун
источник
Не существует необработанных исключений, и основной поток должен работать в течение 30 минут. Я не переопределил __init__. Требуется ли run () тогда? Спасибо
chrissygormley
Я только что понял, что твой пример def MyThread ( threading.thread )... Я предположил, что это были определения классов. Если вы собираетесь создать подкласс threading.thread и инициализировать объект потока с аргументом arg target=Noneили пропустить его target, то потребуется реализация run (). В противном случае, если вы просто хотите запустить простую задачу в другом потоке, смотрите ответ jkp.
Джереми Браун
0

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

Другой пример

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.ThreadPoolExecutor(max_workers=5) as executor:
        for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)):
            print('%d is prime: %s' % (number, prime))

if __name__ == '__main__':
    main()
Jeril
источник