带有importlib模块的Python多进程

带有importlib模块的Python多进程,python,python-3.x,multiprocessing,pickle,python-importlib,Python,Python 3.x,Multiprocessing,Pickle,Python Importlib,您好, 今天我将代码从线程化转移到多进程。一切似乎都正常,直到我出现以下错误: 错误 component.py 类组件(对象): def u u init u u;(self、installmodule、runmodule、installerloc、installationloc、dependencyloc): self.installmodule=installmodule self.runmodule=runmodule self.installerloc=installerloc self

您好,
今天我将代码从
线程化
转移到
多进程
。一切似乎都正常,直到我出现以下错误:

错误 component.py

类组件(对象):
def u u init u u;(self、installmodule、runmodule、installerloc、installationloc、dependencyloc):
self.installmodule=installmodule
self.runmodule=runmodule
self.installerloc=installerloc
self.installationloc=installationloc
self.dependencyloc=dependencyloc
self.config=icnf.Installconfiguration(installerloc+'/conf.conf')
#很多功能。。。
installconfig.py

class State(Enum):
    BEGIN=0 #Look for units
    UNIT=1  #Look for unit keypairs
    KEYPAIR=3

class Phase(Enum):
    NONE=0
    DEPS=1
    PKGS=2

class Installconfiguration(object):
    def __init__(self, config):
        dictionary = self.reader(config) #Fill a dictionary
        #dictionary (key:Phase, value: (dictionary key: str, job))
        self.deps = dictionary[Phase.DEPS]
        self.pkgs = dictionary[Phase.PKGS]
job.py

class Job(object):
    def __init__(self, directory=None, url=None):
        self.directory = directory if directory else ''
        self.url = url if url else ''
如您所见,我将一个组件作为参数传递给
函数phase2(component、str、str、multiprocess.manager.Queue())

component
的构造函数的第二个和第三个参数是使用
importlib
导入的模块


我试过的 我不熟悉python,但不熟悉编程。以下是我尝试过的:

  • 因为错误本身没有指出问题的确切原因,所以我尝试删除arg以找出哪些不能被pickle:Remove
    component
    ,并且一切正常,因此这似乎是出现问题的原因。但是,我需要将此对象传递给我的进程
  • 我在互联网上搜索了几个小时,但除了关于多重处理的基本教程和关于pickle如何工作的解释外,什么也没找到。我确实发现说它应该有用,但不是在窗户上或其他什么东西上。但是,它在Unix(我使用的)上不起作用
我的想法 据我所知,没有任何东西表明我不能发送包含两个importlib模块的类。我不知道
组件
类的确切问题是什么,但importlib模块作为成员是唯一非常规的东西。这就是为什么我认为问题出现在这里


问题: 你知道为什么包含模块的类不适合“酸洗”吗?如何更好地了解
不能pickle
错误发生的原因和位置

更多代码 有关此功能的完整源代码,请访问

对我的问题 请留下评论,要求澄清/更多代码片段/???如果你想让我编辑这个问题

最后的请求 我希望解决方案只使用python标准库,最好使用python 3.3。另外,我的代码要求它在Unix系统上运行

提前谢谢


编辑 根据要求,这里有一个大大简化问题的最小示例:
main.py(可以作为python main.py foo执行)

#/usr/bin/env python
导入系统
导入导入库
导入多处理
类别类别类别(对象):
定义初始值(自身,模块):
自模=模
def foopass(自紧):
self.moduly.foo(stringy)
def barpass(自、细、编号):
自模钢筋(细钢筋)
print('第二个参数:'+str(numbery))
def工人(clazzy,编号):
clazzy.barpass(“哇”,数字)
def main():
clazzy=clazz(importlib.import_模块(sys.argv[1]))
clazzy.foopass('init')
args=[(clazzy,2,)]
将multiprocessing.Pool(processs=2)作为池:
pool.starmap(worker,args)
如果名称=“\uuuuu main\uuuuuuuu”:
main()
foo.py(需要位于上述呼叫建议的同一目录中):

#/usr/bin/env python
全局=0
def foo(stringy):
打印('foo'+stringy)
全球
全局=5
def条(严格):
打印('bar'+stringy)
打印(str(全球))
运行时会出现错误:
TypeError:无法pickle模块对象

现在我们知道酸洗模块对象是不可能的。

为了消除错误,让
clazz
不管多么方便,都不要将模块作为属性,而是让它使用“
modpath
”,这是
importlib
导入用户指定模块所需的字符串。
看起来是这样的(foo.py与上面的完全相同):

#/usr/bin/env python
导入系统
导入导入库
导入多处理
类别类别类别(对象):
定义初始(自我,模式):
self.modpathy=modpathy
def foopass(自紧):
moduley=importlib.import\u模块(self.modpathy)
moduly.foo(stringy)
def barpass(自、细、编号):
moduley=importlib.import\u模块(self.modpathy)
模杆(细杆)
print('第二个参数:'+str(numbery))
def工作人员(clazzy,编号):
克拉齐·巴帕斯(“哇”,数字)
def main():
clazzy=clazz(sys.argv[1])
clazzy.foopass('init')
args=[(clazzy,2,)]
将multiprocessing.Pool(processs=2)作为池:
pool.starmap(worker,args)
如果名称=“\uuuuu main\uuuuuuuu”:
main()
如果您要求保证您的全局变量(如
globaly
)保持状态,则需要传递一个可变对象(如列表、字典)来保存此数据,谢谢@davishering:

模块属性在Python中称为“全局变量”,但它们并不比任何其他数据更持久或更易访问。为什么不用字典呢

示例代码如下所示:

#/usr/bin/env python
导入系统
导入导入库
导入多处理
类别类别类别(对象):
定义初始(自我,模式):
self.modpathy=modpathy
self.dictionary={}
def foopass(自紧):
moduley=importlib.import\u模块(self.modpathy)
moduly.foo(stringy,self.dictionary)
def barpass(自、细、编号):
moduley=importlib.import\u模块(self.modpathy)
模条(stringy,self.dictionary)
print('第二个参数:'+str(numbery))
def工作人员(clazzy,编号):
克拉齐·巴帕斯(“哇”,数字)
def main():
clazzy=clazz(sys.argv[1])
clazzy.foopass('init')
args=[(clazzy,2,)]
将multiprocessing.Pool(processs=2)作为池:
class Job(object):
    def __init__(self, directory=None, url=None):
        self.directory = directory if directory else ''
        self.url = url if url else ''