如何从python线程

时间:2017-03-09 15:55:04

标签: python multithreading python-3.x

我有一个使用Python 3.4.2的非常简单的线程示例。在这个例子中,我创建了一个只返回字符串的五个线程"结果"并将其附加到标题为thread的数组中。在另一个for循环迭代五次中,线程连接到术语x。我正在尝试打印结果x,这应该会产生一个类似于[' Resut','结果''结果''结果& #39;,'结果']而是打印命令只产生线程的标题和它被关闭的事实。我显然误解了如何在python中使用线程。如果有人可以提供一个如何充分完成这个测试用例的例子,我将非常感激。

 import threading

 def Thread_Test():
     return ("Result")

 number  = 5
 threads = []
 for i in range(number):
     Result = threading.Thread(target=Thread_Test)
     threads.append(Result)
     Result.start()

 for x in threads:
     x.join()
 print (x)

2 个答案:

答案 0 :(得分:5)

创建线程和尝试从线程中获取值之间存在差异。一般来说,您绝不应该尝试在线程中使用return来向其调用者提供值。这不是线程的工作方式。当您创建线程对象时,您必须找出一种不同的方法来获取线程中计算的任何值到程序的其他部分。以下是一个简单示例,说明如何使用列表返回值。

#! /usr/bin/env python3
import threading


def main():
    # Define a few variables including storage for threads and values.
    threads_to_create = 5
    threads = []
    results = []
    # Create, start, and store all of the thread objects.
    for number in range(threads_to_create):
        thread = threading.Thread(target=lambda: results.append(number))
        thread.start()
        threads.append(thread)
    # Ensure all threads are done and show the results.
    for thread in threads:
        thread.join()
    print(results)


if __name__ == '__main__':
    main()

如果您绝对坚持必须能够从线程的目标返回值,则可以使用子类覆盖threading.Thread中的某些方法以获得所需的行为。以下显示了更高级的用法,并演示了如果有人希望从新类的run方法继承并覆盖它,多个方法如何需要更改。提供此代码是为了完整性,可能不应使用。

#! /usr/bin/env python3
import sys as _sys
import threading


def main():
    # Define a few variables including storage for threads.
    threads_to_create = 5
    threads = []
    # Create, start, and store all of the thread objects.
    for number in range(threads_to_create):
        thread = ThreadWithReturn(target=lambda: number)
        thread.start()
        threads.append(thread)
    # Ensure all threads are done and show the results.
    print([thread.returned for thread in threads])


class ThreadWithReturn(threading.Thread):

    def __init__(self, group=None, target=None, name=None,
                 args=(), kwargs=None, *, daemon=None):
        super().__init__(group, target, name, args, kwargs, daemon=daemon)
        self.__value = None

    def run(self):
        try:
            if self._target:
                return self._target(*self._args, **self._kwargs)
        finally:
            del self._target, self._args, self._kwargs

    def _bootstrap_inner(self):
        try:
            self._set_ident()
            self._set_tstate_lock()
            self._started.set()
            with threading._active_limbo_lock:
                threading._active[self._ident] = self
                del threading._limbo[self]

            if threading._trace_hook:
                _sys.settrace(threading._trace_hook)
            if threading._profile_hook:
                threading. _sys.setprofile(threading._profile_hook)

            try:
                self.__value = True, self.run()
            except SystemExit:
                pass
            except:
                exc_type, exc_value, exc_tb = self._exc_info()
                self.__value = False, exc_value
                if _sys and _sys.stderr is not None:
                    print("Exception in thread %s:\n%s" %
                          (self.name, threading._format_exc()), file=_sys.stderr)
                elif self._stderr is not None:
                    try:
                        print((
                            "Exception in thread " + self.name +
                            " (most likely raised during interpreter shutdown):"), file=self._stderr)
                        print((
                            "Traceback (most recent call last):"), file=self._stderr)
                        while exc_tb:
                            print((
                                '  File "%s", line %s, in %s' %
                                (exc_tb.tb_frame.f_code.co_filename,
                                    exc_tb.tb_lineno,
                                    exc_tb.tb_frame.f_code.co_name)), file=self._stderr)
                            exc_tb = exc_tb.tb_next
                        print(("%s: %s" % (exc_type, exc_value)), file=self._stderr)
                    finally:
                        del exc_type, exc_value, exc_tb
            finally:
                pass
        finally:
            with threading._active_limbo_lock:
                try:
                    del threading._active[threading.get_ident()]
                except:
                    pass

    @property
    def returned(self):
        if self.__value is None:
            self.join()
        if self.__value is not None:
            valid, value = self.__value
            if valid:
                return value
            raise value


if __name__ == '__main__':
    main()

答案 1 :(得分:1)

请找到以下队列和线程的简单示例,

import threading
import Queue
import timeit

q = Queue.Queue()
number = 5

t1 = timeit.default_timer()
# Step1: For example, we are running multiple functions normally
result = []
def fun(x):
    result.append(x)
    return x

for i in range(number):
    fun(i)
print result ," # normal result"
print (timeit.default_timer() - t1)

t2 = timeit.default_timer()   

#Step2:  by using threads and queue

def fun_thrd(x,q):
    q.put(x)
    return
for i in range(number):
    t1 = threading.Thread(target = fun_thrd, args=(i,q))
    t1.start()
    t1.join()

thrd_result = []

while True:
    if not q.empty():
     thrd_result.append(q.get())
    else:
       break

print thrd_result , "# result with threads involved"
print (timeit.default_timer() - t2)

t3 = timeit.default_timer() 

#step :3 if you want thread to be run without depending on the previous thread

threads = []

def fun_thrd_independent(x,q):
    q.put(x)
    return

def thread_indep(number):
    for i in range(number):
        t = threading.Thread(target = fun_thrd_independent, args=(i,q))
        t.start()
        threads.append(t)

thread_indep(5)

for j in threads:
    j.join()

thread_indep_result = []

while True:
    if not q.empty():
        thread_indep_result.append(q.get())
    else:
       break

print thread_indep_result # result when threads are independent on each other   
print (timeit.default_timer() - t3)

输出:

[0, 1, 2, 3, 4]  # normal result
3.50475311279e-05
[0, 1, 2, 3, 4] # result with threads involved
0.000977039337158
[0, 1, 2, 3, 4]  result when threads are independent on each other
0.000933170318604

根据数据的规模,它会有很大的不同

希望这有帮助,谢谢