【问题标题】:Is it possible to use multiprocessing in a module with windows?是否可以在带有 windows 的模块中使用多处理?
【发布时间】:2016-10-10 18:19:01
【问题描述】:

我目前正在检查一些预先存在的代码,目的是加快速度。有一些地方非常适合并行化。由于 Python 有 GIL,我想我会使用多进程模块。

但是,据我了解,这将在 Windows 上运行的唯一方法是,如果我使用 if __name__=='__main__' 保护从最高级别的脚本调用需要多个进程的函数。然而,这个特定的程序本来是作为一个模块分发和导入的,所以让用户复制和粘贴该保护措施会有点笨拙,我真的很想避免这样做。

就多处理而言,我是不走运还是误解了什么?或者有没有其他方法可以用 Windows 做到这一点?

【问题讨论】:

  • 你会怎么想?
  • Windows 上的@Natecat MP 没有分叉,因此如果没有if \_\_name\_\_,它将像子进程炸弹一样发挥作用。
  • Tyler,考虑了一下,我能看到这个工作的唯一方法是,如果你像在 Windows(基于套接字的服务器)上那样对待 MP 逻辑,并在用户程序的 if 中调用一个服务器对象名称。请记住,它必须非常大或复杂。如果 main 将实例化为myLib.As_master()myLib.As_client(),然后在您的库中检查Is_master(),所有这些都是将静态模块变量设置为True 或False 之类的静态方法。不要让它在你的库中导入任何东西,而是让所有东西都导入它。 1/2
  • 2/2 只是不要把它变成神模块。另外请记住,您只需为使用 MProcessing 的模块导入它。
  • @HarryJohnston Python 可以,但它有一个叫做全局解释器锁的东西,因此一次只有一个线程在执行。 GIL 一直是一个很大的烦恼来源,大量人口一直试图谋杀一段时间 - wiki.python.org/moin/GlobalInterpreterLock

标签: python windows multiprocessing


【解决方案1】:

对于仍在搜索的所有人:

模块内部

from multiprocessing import Process
    
def printing(a):
    print(a)

def foo(name):
    var={"process":{}}
    if name == "__main__":
        for i in range(10):
            var["process"][i] = Process(target=printing , args=(str(i)))
            var["process"][i].start()

        for i in range(10):
            var["process"][i].join

main.py 中

import data

name = __name__

data.foo(name)

输出:

>>2
>>6
>>0
>>4
>>8
>>3
>>1
>>9
>>5
>>7

我是一个完全的菜鸟,所以请不要判断编码或演示,但至少它有效。

【讨论】:

    【解决方案2】:

    正如 cmets 中所解释的,也许你可以做类似的事情

    #client_main.py
    from mylib.mpSentinel import MPSentinel
    
    #client logic
    
    if __name__ == "__main__":
        MPSentinel.As_master()
    
    #mpsentinel.py
    
    class MPSentinel(object):
    
        _is_master = False
    
    @classmethod
    def As_master(cls):
        cls._is_master = True
    
    @classmethod
    def Is_master(cls):
        return cls._is_master
    

    这并不理想,因为它实际上是一个单例/全局的,但它可以解决窗口缺少分叉的问题。您仍然可以使用 MPSentinel.Is_master() 来选择使用多处理,它应该可以防止 Windows 进程轰炸。

    【讨论】:

      【解决方案3】:

      在 ms-windows 上,您应该能够导入程序的 主模块,而不会产生启动进程等副作用。

      当 Python 导入一个模块时,它实际上会运行它。

      因此,一种方法是在 if __name__ is '__main__' 块中。

      另一种方法是在函数中进行。

      以下内容不适用于 ms-windows:

      from multiprocessing import Process
      
      def foo():
          print('hello')
      
      p = Process(target=foo)
      p.start()
      

      这是因为它在导入模块时尝试启动一个进程。

      编程指南中的以下示例是可以的:

      from multiprocessing import Process, freeze_support, set_start_method
      
      def foo():
          print('hello')
      
      if __name__ == '__main__':
          freeze_support()
          set_start_method('spawn')
          p = Process(target=foo)
          p.start()
      

      因为导入模块时 if 块中的代码没有运行。

      但是把它放在一个函数中也应该可以:

      from multiprocessing import Process
      
      def foo():
          print('hello')
      
      def bar()
          p = Process(target=foo)
          p.start()
      

      当这个模块运行时,它会定义两个新函数,然后不运行。

      【讨论】:

      • 无论谁编写使用该模块的程序,仍然需要编写自己的if __name__ == '__main__' 守卫。问题是问是否有办法避免这种情况。
      猜你喜欢
      • 2011-05-03
      • 2020-06-03
      • 1970-01-01
      • 2011-07-21
      • 2017-07-04
      • 2020-11-16
      • 1970-01-01
      • 2017-02-18
      • 2022-06-19
      相关资源
      最近更新 更多