可以使用multiprocessing.managers 模块来实现您想要的。不过,它确实需要少量的黑客攻击。
给定一个具有您想要公开的功能的模块,那么您需要创建一个可以为这些功能创建代理的Manager。
为 py3 函数提供代理服务的管理器进程:
from multiprocessing.managers import BaseManager
import spam
class SpamManager(BaseManager):
pass
# Register a way of getting the spam module.
# You can use the exposed arg to control what is exposed.
# By default only "public" functions (without a leading underscore) are exposed,
# but can only ever expose functions or methods.
SpamManager.register("get_spam", callable=(lambda: spam), exposed=["add", "sub"])
# specifying the address as localhost means the manager is only visible to
# processes on this machine
manager = SpamManager(address=('localhost', 50000), authkey=b'abc',
serializer='xmlrpclib')
server = manager.get_server()
server.serve_forever()
我重新定义了 spam 以包含两个名为 add 和 sub 的函数。
# spam.py
def add(x, y):
return x + y
def sub(x, y):
return x - y
使用SpamManager公开的py3函数的客户端进程。
from __future__ import print_function
from multiprocessing.managers import BaseManager
class SpamManager(BaseManager):
pass
SpamManager.register("get_spam")
m = SpamManager(address=('localhost', 50000), authkey=b'abc',
serializer='xmlrpclib')
m.connect()
spam = m.get_spam()
print("1 + 2 = ", spam.add(1, 2)) # prints 1 + 2 = 3
print("1 - 2 = ", spam.sub(1, 2)) # prints 1 - 2 = -1
spam.__name__ # Attribute Error -- spam is a module, but its __name__ attribute
# is not exposed
设置后,此表单提供了一种访问函数和值的简单方法。它还允许以类似的方式使用这些函数和值,如果它们不是代理,则可以使用它们。最后,它允许您在服务器进程上设置密码,以便只有授权的进程才能访问管理器。管理器长时间运行,也意味着不必为您进行的每个函数调用启动一个新进程。
一个限制是我使用xmlrpclib 模块而不是pickle 在服务器和客户端之间来回发送数据。这是因为 python2 和 python3 对pickle 使用不同的协议。您可以通过将自己的客户端添加到 multiprocessing.managers.listener_client 来解决此问题,该客户端使用商定的协议来酸洗对象。