سؤال

كيف يمكنني الحصول على مؤشر ترابط لإرجاع tuple أو أي قيمة خياري مرة أخرى إلى الوالد في بيثون؟

هل كانت مفيدة؟

المحلول

أقترح عليك إنشاء مثيل Queue.queue. قبل بدء تشغيل الخيط، وتمريرها كواحد من Args مؤشر الترابط: قبل انتهاء الموضوع، فإنه .putS النتيجة في قائمة الانتظار التي تلقتها كوسيطة. الوالد يمكن .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)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top