使用上下文管理器的好处是什么多重处理。经理?

2024-09-30 02:17:11 发布

您现在位置:Python中文网/ 问答频道 /正文

the documentation中,Manager与上下文管理器(即with)一起使用,如下所示:

from multiprocessing.managers import BaseManager

class MathsClass:
    def add(self, x, y):
        return x + y
    def mul(self, x, y):
        return x * y

class MyManager(BaseManager):
    pass

MyManager.register('Maths', MathsClass)

if __name__ == '__main__':
    with MyManager() as manager:
        maths = manager.Maths()
        print(maths.add(4, 3))         # prints 7
        print(maths.mul(7, 8))         # prints 56

但是除了名称空间之外,这有什么好处呢?对于打开文件流,好处非常明显,因为您不必手动.close()连接,但是对于Manager来说是什么呢?如果不在上下文中使用它,那么您必须使用哪些步骤来确保所有内容都已正确关闭?你知道吗

简言之,使用上述方法的好处是什么

manager = MyManager()
maths = manager.Maths()
print(maths.add(4, 3))         # prints 7
print(maths.mul(7, 8))         # prints 56

Tags: selfadddefwithmanagerprintsclassprint
1条回答
网友
1楼 · 发布于 2024-09-30 02:17:11

But what is the benefit of this (...)?

首先,您可以从几乎所有上下文管理器中获得主要好处。您有一个明确定义的资源生存期。它是在with ...:块打开时分配和获取的。当块结束时释放它(通过到达结尾或引发异常)。每当垃圾回收器找到它时,它仍然会被释放,但是由于外部资源已经被释放,所以这就不那么重要了。你知道吗

multiprocessing.Manager(这是一个返回SyncManager的函数,尽管Manager看起来很像一个类)的情况下,资源是一个保存状态的“服务器”进程和许多共享该状态的工作进程。你知道吗

what is [the benefit of using a context manager] for Manager?

如果不使用上下文管理器并且不在管理器上调用shutdown,那么“服务器”进程将继续运行,直到SyncManager__del__运行为止。在某些情况下,这可能发生在创建SyncManager的代码完成后不久(例如,如果它是在一个短函数中创建的,并且函数返回正常,并且您正在使用CPython,那么引用计数系统可能会很快注意到对象已死亡,并调用其__del__)。在其他情况下,可能需要更长的时间(如果引发异常并保留对管理器的引用,则在处理该异常之前,它将保持活动状态)。在某些不好的情况下,它可能根本不会发生(如果SyncManager在引用循环中结束,那么它的__del__将阻止循环收集器收集它;或者在调用__del__之前,您的进程可能会崩溃)。在所有这些情况下,您将放弃对清理SyncManager创建的额外Python进程的控制。这些进程可能表示系统上的非平凡资源使用情况。在非常糟糕的情况下,如果您在一个循环中创建SyncManager,那么最终可能会创建许多同时存在的循环,并且很容易消耗大量资源。你知道吗

If you don't use it in a context, what steps do you have to use to ensure that everything is closed properly?

您必须自己实现上下文管理器协议,就像您在没有with的情况下使用的任何上下文管理器一样。在纯Python中这样做是很困难的,但仍然是正确的。比如:

manager = None
try:
    manager = MyManager()
    manager.__enter__()
    # use it ...
except:
    if manager is not None:
        manager.__exit__(*exc_info())
else:
    if manager is not None:
        manager.__exit__(None, None, None)

startshutdown也分别是__enter____exit__的别名。你知道吗

相关问题 更多 >

    热门问题