简体   繁体   中英

How do I access data from a python thread

I have a very simple threading example using Python 3.4.2. In this example I am creating a five threads that just returns the character string "Result" and appends it to an array titled thread. In another for loop iterated five times the threads are joined to the term x. I am trying to print the result x, which should yield a list that looks like ['Resut','Result','Result','Result','Result'] but instead the print command only yields the title of the thread and the fact that it is closed. Im obviously misunderstanding how to use threads in python. If someone could provide an example of how to adequately complete this test case I would be very grateful.

 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)

There is a difference between creating a thread and trying to get values out of a thread. Generally speaking, you should never try to use return in a thread to provide a value back to its caller. That is not how threads work. When you create a thread object, you have to figure out a different way of get any values calculated in the thread to some other part of your program. The following is a simple example showing how values might be returned using a list.

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

If you absolutely insist that you must have the ability to return values from the target of a thread, it is possible to override some methods in threading.Thread using a child class to get the desired behavior. The following shows more advanced usage and demonstrates how multiple methods require a change in case someone desires to inherit from and override the run method of the new class. This code is provided for completeness and probably should not be used.

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

please find the below simple example for queue and threads,

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)

output:

[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

It will hugely differ according to the scale of the data

Hope this helps, Thanks

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM