【问题标题】:Python Multiprocessing: Reloading module in child effecting parentPython Multiprocessing:在影响父级的子级中重新加载模块
【发布时间】:2015-11-19 22:53:12
【问题描述】:

我觉得我应该在这个问题前加上以下陈述:我知道在 python 中重新加载模块是不受欢迎的。我更多的是在修补 Python 并做一些事情来证明我可以。

假设我在主文件中有这段代码:

def reloadFoo():
    lastReloadedTime = time.time()
    while True: 
      if os.stat(foo.__file__).st_mtime > lastReloadedTime: 
         lastReloadedTime = time.time()
         reload(foo)

而 foo.py 包含

def printMe():
    print "Yo ho yo ho"

如果我调用reloadFoo(),如果它自上次重新加载后被修改过,它将永远重新加载模块。但是我如何使它作为某种背景功能工作呢?

我研究了多处理,所以我在 main 中有这样的东西:

import foo

def reloadFoo():
....
reloadProc = multiprocessing.Process(target=reloadFoo)
reloadProc.start()
...
while True:
   foo.printMe()
   time.sleep(20)

但看起来如果我将 foo.py 的 printMe 更改为打印“A Pirate's Life for Me”,它会重新加载模块,但不会“影响”父进程(以及未来的子进程):循环仍然打印“哟嗬嗬嗬”

我尝试将管道的一端发送到 reloadFoo,但我仍然不得不在主的 while 循环中调用 reloadFoo()(我猜这违背了它开始有一个子进程的目的)。

实际问题:有没有办法让子进程重新加载模块,并且它也会在父进程(以及未来的子进程)中重新加载?

【问题讨论】:

  • 您真正需要的是文件系统事件通知。您会在 pypi.python.org/pypi/watchdog 找到一个提供该服务的图书馆。在该页面上还有一个替代列表。
  • 没有简单的方法让子进程更改父进程命名空间的一部分。但是为什么在这里使用一个过程呢?您可以轻松地改用线程,因为您正在做的工作不是非常占用 CPU 资源。虽然,我猜你写它的方式,reloadFoo 函数会在轮询文件系统以查看文件是否已更改。我建议在无限循环中添加一个简短的sleep!

标签: python multithreading python-2.7 multiprocessing python-module


【解决方案1】:

子进程不能以这种方式直接影响其父进程。将 Python 添加到组合中,几乎不可能以一种可以满足您需求的方式进行操作。

你说你知道重新加载模块是不受欢迎的,你只是在“修补”,但是你接着说 实际问题:有没有办法让子进程重新加载模块它还会在父进程(以及未来的子进程)中重新加载?

所以既然你已经问了这个问题,我还是会给出你不想要的答案,因为 Stack Overflow 不仅仅是关于最初的提问者 :-)

重新加载模块并没有因为美观而受到反对;重新加载模块是不受欢迎的,因为在任何实际系统中,重新加载模块都不太可能满足您的需求,即使您不尝试从不同的进程执行此操作.

例如,让我们创建一个名为 reloadme.py 的简单模块:

class MyClass(object):
    def __init__(self, value=0):
        self.value = value
    def __eq__(self, other):
        return type(self) is type(other) and self.value == other.value

它有一个单一的类定义,这个类可以做的一件事是允许它的实例查看它们是否与它的其他实例相等。 (这本身是相当不符合 Python 的,因为它没有使用鸭子类型,但它仍然是一种非常简单的方式来说明现实世界中的问题, 在任何规模的系统中都会出现。)所以让我们使用这个模块:

>>> import reloadme
>>> x = reloadme.MyClass()
>>> y = reloadme.MyClass()
>>> reload(reloadme)
>>> z = reloadme.MyClass()
>>> x == y
True
>>> x == z
False

即使您已经成功地重新加载了模块,系统中仍然存在旧模块的零碎。清理它们真的既痛苦又费时,不清理它们会给你带来调试方面的麻烦,让你怀疑自己的理智。

不过,可能有充分的理由这样做,例如永远不会崩溃的系统。但这并不是一件容易的事,而且在大多数情况下,它的效率并不高。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-15
    • 1970-01-01
    • 2018-08-23
    • 2012-01-17
    相关资源
    最近更新 更多