สร้างหัวข้อในหลาม


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'

คำตอบ:


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

ที่นี่ฉันจะแสดงวิธีการใช้โมดูลเธรดเพื่อสร้างเธรดที่เรียกใช้ฟังก์ชันปกติเป็นเป้าหมาย คุณสามารถดูว่าฉันสามารถส่งผ่านอาร์กิวเมนต์ใด ๆ ที่ฉันต้องการในตัวสร้างเธรดได้อย่างไร


ฉันได้ลองสิ่งนี้แล้ว ฉันได้เพิ่มสคริปต์ด้านบน คุณช่วยบอกฉันได้อย่างไรว่าจะให้ฟังก์ชันที่สองทำงานควบคู่ไปกับฟังก์ชันแรกได้อย่างไร ขอบคุณ
chrissygormley

6
@chrissygormley: เข้าร่วมบล็อก () จนกว่าเธรดแรกจะเสร็จสิ้น
FogleBird

4
@chrissygormley: ตามที่กล่าวไว้เข้าร่วมบล็อกจนกว่าเธรดที่คุณกำลังเข้าร่วมจะเสร็จสิ้นดังนั้นในกรณีของคุณให้เริ่มเธรดที่สองด้วยฟังก์ชันที่สองของคุณเป็นเป้าหมายในการรันทั้งสองฟังก์ชั่นแบบเคียงข้างกัน คุณเพียงแค่ต้องการรอจนกว่าจะเสร็จ
jkp

41
ผมเก็บไว้อ่านexitingเป็นexcitingซึ่งผมคิดว่าเป็นที่เหมาะสมมากขึ้นอยู่แล้ว
Chase Roberts

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

Doc สำหรับthread.start_new_thread


2
อาร์กิวเมนต์ที่สองจะต้องเป็นtupleสำหรับthread.start_new_thread(function, args[, kwargs])
venkatvb

13

ฉันพยายามเพิ่มการเข้าร่วมอีกครั้ง () และดูเหมือนว่าใช้งานได้ นี่คือรหัส

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

3

คุณสามารถใช้targetอาร์กิวเมนต์ในคอนสตรัคจะผ่านโดยตรงในฟังก์ชั่นที่ได้รับการเรียกแทนThreadrun


2

คุณแทนที่เมธอด run () หรือไม่ หากคุณลบล้าง__init__คุณแน่ใจหรือไม่ว่าเรียกฐานthreading.Thread.__init__()?

หลังจากเริ่มต้นเธรดสองเธรดเธรดหลักยังคงทำงาน / บล็อก / เข้าร่วมอย่างต่อเนื่องบนเธรดย่อยเพื่อให้การดำเนินการเธรดหลักไม่สิ้นสุดก่อนที่เธรดย่อยจะทำงานให้เสร็จสมบูรณ์หรือไม่?

และสุดท้ายคุณจะได้รับข้อยกเว้นที่ไม่สามารถจัดการได้หรือไม่?


ไม่มีข้อยกเว้นที่ไม่สามารถจัดการได้และเธรดหลักควรรันเป็นเวลา 30 นาที __init__ผมไม่ได้แทนที่ จำเป็นต้องเรียกใช้ () หรือไม่ ขอบคุณ
chrissygormley

ฉันเพิ่งตระหนักว่าตัวอย่างของคุณคือdef MyThread ( threading.thread )... ฉันคิดว่านั่นเป็นคำจำกัดความของชั้นเรียน หากคุณกำลังจะ subclass threading.thread และเริ่มต้นวัตถุด้ายด้วยtarget=Noneหรือละเว้นtargetหาเรื่องแล้วการดำเนินงานของ run () จะต้อง มิฉะนั้นถ้าคุณเพียงแค่ต้องการทำงานง่ายๆในเธรดอื่นให้ดูคำตอบของ jkp
Jeremy Brown

0

งูหลาม 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()
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.