【问题标题】:python multiprocessing classpython多处理类
【发布时间】:2017-12-22 10:58:59
【问题描述】:

我在这段代码中遇到了奇怪的 python 行为:

#!/usr/bin/python

import multiprocessing
import time
import sys

class worker(multiprocessing.Process):

    def __init__(self, val):
        super(worker,self).__init__()
        self.val = val

    def update_val(self,val):
        self.val = val
        print("self.val now is %s" %(self.val))

    def run(self):
        while True:
            print("Worker report: val is %s" % (self.val))
            time.sleep(self.val)


subproc = worker(10)
subproc.start()
while True:
    new_val =  sys.stdin.readline().rstrip()
    if new_val:
        subproc.update_val(new_val)
    print("Main report: val is %s" % (subproc.val))

我希望,对象subproc 中的变量valupdate_val 函数更改。 但我很惊讶,因为该变量仅针对来自main 进程的查询进行了更改。 函数run 仍然使用旧值:

$ ./test.py
Worker report: val is 10
Worker report: val is 10
5
self.val now is 5
Main report: val is 5

Main report: val is 5
Worker report: val is 10
Worker report: val is 10

问题可能是什么原因?此代码在 Python2.7Python3.6 中的工作方式类似。提前致谢!

【问题讨论】:

    标签: python class python-multiprocessing


    【解决方案1】:

    Multiprocessing 会产生一个 进程来复制您所在的当前进程(及其内存状态),因此您无法从当前进程访问该新进程,您应该为此与它们通信。

    查看进程之间的sharing stateexchanging objects

    【讨论】:

    • 我希望避免使用共享变量。无论如何,谢谢!
    • @J.Doe,是的,你可以使用线程而不是处理,这取决于你必须做什么。
    • 线程是不可杀死的,我知道。如果线程挂在“readline()”上,我无法对它们做任何事情。
    • @J.Doe,它会挂在 readline 因为它是一个阻塞调用,如果它发生,你可以捕获一个异常并将某种标志设置为 true 以使主线程产生另一个读取线程.这样,它就不会与另一个过程不同。此外,当您的进程退出时,它也会终止线程。
    • 是的,但问题在于,线程必须在 PTY 上“读取”不可预测的时间量。在这个阻塞调用期间,主程序可以决定关闭这个线程。这是一个问题,因为这个被阻塞的线程不能被加入或杀死。
    【解决方案2】:

    如果您可以使用threading 而不是multiprocessing,请尝试以下代码。 我只是将multiprocessing 更改为threading 并将线程对象的daemon 属性设置为True

    守护进程

    指示此线程是否为守护进程的布尔值 线程(真)或不(假)。这必须在 start() 之前设置 调用,否则引发 RuntimeError。它的初始值为 从创建线程继承;主线程不是守护进程 线程,因此在主线程中创建的所有线程默认为 守护进程 = False。

    当没有存活的非守护线程时整个 Python 程序退出 离开了。

    简而言之,如果您的worker thread 设置为daemon=True 并且main thread 退出,则worker thread 也会退出,因为没有non-daemon thread 活着(main thread 必须是non-daemon thread)。

    你可以通过KeyboardInterrupt(Ctrl+c)简单地退出整个程序。

    import threading
    import time
    import sys
    
    
    class worker(threading.Thread):
    
        def __init__(self, val):
            super(worker, self).__init__()
            self.val = val
    
        def update_val(self, val):
            if val.isdigit():
                self.val = int(val)
                print("self.val now is %s" % (self.val))
            else:
                print("val should be digit")
    
        def run(self):
            while True:
                print("Worker report: val is %s" % (self.val))
                time.sleep(self.val)
    
    
    subproc = worker(10)
    subproc.daemon = True    # By setting daemon, the threading will be killed when main thread exit.
    subproc.start()
    while True:
        new_val = sys.stdin.readline().rstrip()
        if new_val:
            subproc.update_val(new_val)
        print("Main report: val is %s" % (subproc.val))
    

    【讨论】:

      【解决方案3】:

      工作代码:

      #!/usr/bin/python
      import multiprocessing
      import time
      import sys
      
      class worker(multiprocessing.Process):
      
          def __init__(self, valobj):
              super(worker,self).__init__()
              self.val = valobj
      
          def run(self):
              while True:
                  print("Worker report: val is %s" % (self.val.value))
                  time.sleep(self.val.value)
      
      
      valobj = multiprocessing.Value('i', 5)
      subproc = worker(valobj)
      subproc.start()
      while True:
          new_val =  sys.stdin.readline().rstrip()
          if new_val:
              valobj.value = int(new_val)
          print("Main report: val is %s" %(valobj.value))
      

      此代码具有所需的行为:

      $ ./test.py
      Worker report: val is 5
      1
      Main report: val is 1
      
      Main report: val is 1
      
      Main report: val is 1
      Worker report: val is 1
      Worker report: val is 1
      Worker report: val is 1
      3
      Main report: val is 3
      Worker report: val is 3
      Worker report: val is 3
      

      【讨论】:

      • 如果您不强调并解释差异,这并不是一个很好的答案。
      • 是的,忘记了。
      猜你喜欢
      • 2022-01-23
      • 2014-08-04
      • 1970-01-01
      • 2017-04-12
      • 2016-01-19
      • 2015-05-21
      • 2016-11-21
      • 2011-04-20
      • 2016-05-30
      相关资源
      最近更新 更多