قيمة العودة من الموضوع
-
19-09-2019 - |
سؤال
كيف يمكنني الحصول على مؤشر ترابط لإرجاع tuple أو أي قيمة خياري مرة أخرى إلى الوالد في بيثون؟
المحلول
أقترح عليك إنشاء مثيل Queue.queue. قبل بدء تشغيل الخيط، وتمريرها كواحد من Args مؤشر الترابط: قبل انتهاء الموضوع، فإنه .put
S النتيجة في قائمة الانتظار التي تلقتها كوسيطة. الوالد يمكن .get
أو .get_nowait
في الإرادة.
قائمة الانتظار هي عموما أفضل طريقة لترتيب مزامنة المعلومات والاتصالات في بيثون: إنها آمنة من الخيط في جوهرها، ومركبات مركبات مرور الرسائل - أفضل طريقة لتنظيم تعدد المهام بشكل عام! -)
نصائح أخرى
إذا كنت تتصل بالانضمام () لانتظار اكتمال الموضوع، فيمكنك ببساطة إرفاق النتيجة إلى مثيل مؤشر الترابط نفسه ثم استرجعها من الخيط الرئيسي بعد إرجاع الانضمام ().
من ناحية أخرى، لا تخبرنا كيف تنوي اكتشاف أن الخيط يتم وأن تكون النتيجة متاحة. إذا كان لديك بالفعل طريقة للقيام بذلك، فمن المحتمل أن تشيرك (ولنا، إذا كنت تخبرنا) بأفضل طريقة للحصول على النتائج.
يجب عليك اجتياز مثيل قائمة الانتظار كمعلمة ثم يجب عليك. dut () كائن الإرجاع الخاص بك في قائمة الانتظار. يمكنك جمع قيمة الإرجاع عبر Queue.get () مهما كان الكائن الذي وضعته.
عينة:
queue = Queue.Queue()
thread_ = threading.Thread(
target=target_method,
name="Thread1",
args=[params, queue],
)
thread_.start()
thread_.join()
queue.get()
def target_method(self, params, queue):
"""
Some operations right here
"""
your_return = "Whatever your object is"
queue.put(your_return)
استخدام مؤلحات متعددة:
#Start all threads in thread pool
for thread in pool:
thread.start()
response = queue.get()
thread_results.append(response)
#Kill all threads
for thread in pool:
thread.join()
يمكنني استخدام هذا التنفيذ ويعمل بشكل رائع بالنسبة لي. أتمنى لك أن تفعل ذلك.
يستخدم Lambda. لفك وظيفة مؤشر الترابط المستهدف وتمرير قيمة الإرجاع مرة أخرى إلى الخيط الأم باستخدام طابور. وبعد (لا تزال الوظيفة المستهدفة الأصلية دون تغيير دون معلمة قائمة انتظار إضافية.)
عينة من الرموز:
import threading
import queue
def dosomething(param):
return param * 2
que = queue.Queue()
thr = threading.Thread(target = lambda q, arg : q.put(dosomething(arg)), args = (que, 2))
thr.start()
thr.join()
while not que.empty():
print(que.get())
انتاج:
4
أنا مندهش من أي شخص ذكر أنه يمكنك فقط تمريره
>>> thread_return={'success': False}
>>> from threading import Thread
>>> def task(thread_return):
... thread_return['success'] = True
...
>>> Thread(target=task, args=(thread_return,)).start()
>>> thread_return
{'success': True}
ربما هذا له القضايا الرئيسية التي أنا غير مدركين.
نهج آخر هو تمرير وظيفة رد الاتصال إلى الخيط. هذا يعطي طريقة بسيطة وآمنة ومرنة لإرجاع قيمة إلى الوالد، في أي وقت من الخيط الجديد.
# A sample implementation
import threading
import time
class MyThread(threading.Thread):
def __init__(self, cb):
threading.Thread.__init__(self)
self.callback = cb
def run(self):
for i in range(10):
self.callback(i)
time.sleep(1)
# test
import sys
def count(x):
print x
sys.stdout.flush()
t = MyThread(count)
t.start()
يمكنك استخدام متزامنة طابور وحدة.
ضع في اعتبارك أنك بحاجة إلى التحقق من قاعدة بيانات المستخدم من قاعدة البيانات مع معرف معروف:
def check_infos(user_id, queue):
result = send_data(user_id)
queue.put(result)
الآن يمكنك الحصول على بياناتك مثل هذا:
import queue, threading
queued_request = queue.Queue()
check_infos_thread = threading.Thread(target=check_infos, args=(user_id, queued_request))
check_infos_thread.start()
final_result = queued_request.get()
POC:
import random
import threading
class myThread( threading.Thread ):
def __init__( self, arr ):
threading.Thread.__init__( self )
self.arr = arr
self.ret = None
def run( self ):
self.myJob( self.arr )
def join( self ):
threading.Thread.join( self )
return self.ret
def myJob( self, arr ):
self.ret = sorted( self.arr )
return
#Call the main method if run from the command line.
if __name__ == '__main__':
N = 100
arr = [ random.randint( 0, 100 ) for x in range( N ) ]
th = myThread( arr )
th.start( )
sortedArr = th.join( )
print "arr2: ", sortedArr
حسنا، في وحدة خيوط Python، هناك كائنات حالة مرتبطة بالأقفال. طريقة واحدة acquire()
سيعود أي قيمة يتم إرجاعها من الطريقة الأساسية. للمزيد من المعلومات: كائنات حالة بيثون
بناء على اقتراح JCOMEAU_ICTX. أبسط واحدة صادفت. المتطلب هنا هو الحصول على Staus حالة الخروج من ثلاث عمليات مختلفة تعمل على الخادم وتشغيل برنامج نصي آخر إذا كانت الثلاثة ناجحة. يبدو أن هذا يعمل بشكل جيد
class myThread(threading.Thread):
def __init__(self,threadID,pipePath,resDict):
threading.Thread.__init__(self)
self.threadID=threadID
self.pipePath=pipePath
self.resDict=resDict
def run(self):
print "Starting thread %s " % (self.threadID)
if not os.path.exists(self.pipePath):
os.mkfifo(self.pipePath)
pipe_fd = os.open(self.pipePath, os.O_RDWR | os.O_NONBLOCK )
with os.fdopen(pipe_fd) as pipe:
while True:
try:
message = pipe.read()
if message:
print "Received: '%s'" % message
self.resDict['success']=message
break
except:
pass
tResSer={'success':'0'}
tResWeb={'success':'0'}
tResUisvc={'success':'0'}
threads = []
pipePathSer='/tmp/path1'
pipePathWeb='/tmp/path2'
pipePathUisvc='/tmp/path3'
th1=myThread(1,pipePathSer,tResSer)
th2=myThread(2,pipePathWeb,tResWeb)
th3=myThread(3,pipePathUisvc,tResUisvc)
th1.start()
th2.start()
th3.start()
threads.append(th1)
threads.append(th2)
threads.append(th3)
for t in threads:
print t.join()
print "Res: tResSer %s tResWeb %s tResUisvc %s" % (tResSer,tResWeb,tResUisvc)
# The above statement prints updated values which can then be further processed
سوف تغلب وظيفة المجمع التالية وظيفة موجودة وإرجاع كائن يشير إلى الموضوع إلى الموضوع (بحيث يمكنك الاتصال start()
,join()
, ، وما إلى ذلك) وكذلك الوصول / عرض قيمة العودة في نهاية المطاف.
def threadwrap(func,args,kwargs):
class res(object): result=None
def inner(*args,**kwargs):
res.result=func(*args,**kwargs)
import threading
t = threading.Thread(target=inner,args=args,kwargs=kwargs)
res.thread=t
return res
def myFun(v,debug=False):
import time
if debug: print "Debug mode ON"
time.sleep(5)
return v*2
x=threadwrap(myFun,[11],{"debug":True})
x.thread.start()
x.thread.join()
print x.result
يبدو حسنا، و threading.Thread
يبدو أن الطبقة تمتد بسهولة (*) مع هذا النوع من الوظائف، لذلك أتساءل لماذا ليس هناك بالفعل. هل هناك عيب مع الطريقة المذكورة أعلاه؟
(*) لاحظ أن إجابة Husanu لهذا السؤال لا تفعل ذلك بالضبط threading.Thread
مما أدى إلى إصدار join()
يعطي قيمة الإرجاع.
بالنسبة للبرامج السهلة، تبدو الإجابات المذكورة أعلاه قليلا مثل المبالغة بالنسبة لي. أود أن نيسن النهج القابل للتغيير:
class RetVal:
def __init__(self):
self.result = None
def threadfunc(retVal):
retVal.result = "your return value"
retVal = RetVal()
thread = Thread(target = threadfunc, args = (retVal))
thread.start()
thread.join()
print(retVal.result)