如何在此过程中使用.join

时间:2013-07-31 17:56:44

标签: python join process hang

您好我正在创建此工作器生成器类,我在终止时挂起我知道我需要使用.join来关闭它们但我无法弄清楚如何将进程名称传递给{{ 1}}功能。我的想法以某种方式将它保存为全局变量,我在想一本字典。然后是时候让工作人员终止terminate访问该功能变量并在消息队列中放入毒丸后终止适用的进程

terminate

你们和gals的任何想法都会受到赞赏我并没有坚持任何特定的方式来做这件事我对python有点新意,所以欢迎任何建议!

编辑:完整代码

class worker_manager:
      i = test_imports()
      #someVarForP 
      #someVarForP2 

      def generate(control_queue, threadName, runNum):
          if threadName == 'one':
              print ("Starting import_1 number %d") % runNum
              p = multiprocessing.Process(target=i.import_1, args=(control_queue, runNum))
              #someVarForP = p
              p.start()        
          if threadName == 'two': 
              print ("Starting import_2 number %d") % runNum
              p = multiprocessing.Process(target=i.import_2, args=(control_queue, runNum))
              #someVarForP2 = p2
              p.start()
          if threadName == 'three':    
              p = multiprocessing.Process(target=i.import_1, args=(control_queue, runNum))
              print ("Starting import_1 number %d") % runNum
              p2 = multiprocessing.Process(target=i.import_2, args=(control_queue, runNum))
              print ("Starting import_2 number %d") % runNum
              #someVarForP = p
              #someVarForP2 = p2
              p.start()
              p2.start()

      def terminate(threadName):
           if threadName == 'one':
               #self.someVarForP.join()
           if threadName == 'two':
               #self.someFarForP2.join()
           if threadName == 'three':
               #self.someVarForP.join()
               #self.someVarForP2.join()

仅编辑import multiprocessing import time class test_imports:#Test classes remove def import_1(self, control_queue, thread_number): print ("Import_1 number %d started") % thread_number run = True count = 1 while run: alive = control_queue.get() if alive == 't1kill': print ("Killing thread type 1 number %d") % thread_number run = False break print ("Thread type 1 number %d run count %d") % (thread_number, count) count = count + 1 def import_2(self, control_queue, thread_number): print ("Import_1 number %d started") % thread_number run = True count = 1 while run: alive = control_queue.get() if alive == 't2kill': print ("Killing thread type 2 number %d") % thread_number run = False break print ("Thread type 2 number %d run count %d") % (thread_number, count) count = count + 1 class worker_manager: # ... names = {'one': 'import_1', 'two': 'import_2'} def __init__(self): self.children = {} def generate(self, control_queue, threadName, runNum): name = self.names[threadName] target = i.getattr(name) print ("Starting %s number %d") % (name, runNum) p = multiprocessing.Process(target=target, args=(control_queue, runNum)) self.children[threadName] = p p.start() def terminate(self, threadName): self.children[threadName].join() if __name__ == '__main__': # Establish communication queues control = multiprocessing.Queue() manager = worker_manager() runNum = int(raw_input("Enter a number: ")) threadNum = int(raw_input("Enter number of threads: ")) threadName = raw_input("Enter number: ") thread_Count = 0 print ("Starting threads") for i in range(threadNum): if threadName == 'three': manager.generate(control, 'one', i) manager.generate(control, 'two', i) manager.generate(control, threadName, i) thread_Count = thread_Count + 1 if threadName == 'three': thread_Count = thread_Count + 1 time.sleep(runNum)#let threads do their thing print ("Terminating threads") for i in range(thread_Count): control.put("t1kill") control.put("t2kill") if threadName == 'three': manager.terminate('one') manager.terminate('two') else: manager.terminate(threadName) 是实际将要使用的唯一一点。剩下的工作只是为了开发它。

1 个答案:

答案 0 :(得分:1)

首先,如果您从名为join的函数中使用它,我不确定您是否了解terminate的作用。当您调用join时,所有这一切都会使您的父进程等待子进程完成。你仍然需要告诉子进程它需要完成(例如,通过在队列中发布一些东西,或发送信号),或者你最终会等待。

其次,你从方法中留下self参数,使用了旧式类,创建了一个你可能需要实例属性的类属性,并开始讨论全局变量看起来非常适合实例属性的东西意味着你可能对类有一些误解。

但是最大的问题似乎是你想要将字符串名称映射到实例属性(或其他类型的变量)。当可以执行此操作时,you almost never want to。不要为每个名称使用单独的属性,只需使用单个dict,每个名称都有一个值。例如:

class worker_manager:
    # ...
    def __init__(self):
        self.children = {}
    def generate(self, control_queue, threadName, runNum):
        if threadName == 'one':
            print ("Starting import_1 number %d") % runNum
            p = multiprocessing.Process(target=i.import_1, args=(control_queue, runNum))
            self.children[threadName]
            p.start()
        # ...
    def terminate(self, threadName):
        self.children[threadName].join()

您可以通过分解if块的公共部分来进一步清理它。例如,您可能需要一个调度表。而且,虽然我们正在使用它,但是让我们使用更多的标准名称,4个字符的缩进而不是随机,新的类等等:

class WorkerManager(object):
    # ...
    names = {'one': 'import_1', 'two': 'import_2', 'three': 'import_3'}
    def __init__(self):
        self.children = {}
    def generate(self, control_queue, threadName, runNum):
        name = WorkerManager.names[threadName]
        target = i.getattr(name)
        print ("Starting %s number %d") % (name, runNum)
        p = multiprocessing.Process(target=target, args=(control_queue, runNum))
        self.children[threadName] = p
        p.start()
    def terminate(self, threadName):
        self.children[threadName].join()

如果我们能够看到更多代码,那么可能会有很多重构,但这应该足以让你开始。