我有一个Django项目,该项目使用celery进行异步任务处理。我正在使用python 2.7。
我在Django项目的模块client.py
中有一个类:
# client.py
class Client:
def __init__(self):
# code for opening a persistent connection and saving the connection client in a class variable
...
self.client = <connection client>
def get_connection_client(self):
return self.client
def send_message(self, message):
# --- Not the exact code but this is the function I need to access to for which I need access to the client variable---
self.client.send(message)
# Other functions that use the above method to send messages
...
该类只需要实例化一次即可创建与远程服务器的持久连接。
我运行无限期运行的脚本connection.py
:
# connection.py
from client import Client
if __name__ == '__main__':
clientobj = Client()
client = clientobj.get_connection_client()
# Blocking process
while True:
# waits for a message from the remote server
...
我需要从另一个模块client
(芹菜需要)访问变量tasks.py
。
# tasks.py
...
from client import Client
@app.task
def function():
# Need access to the client variable
# <??? How do I get an access to the client variable for the
# already established connection???>
message = "Message to send to the server using the established connection"
client.send_message(message)
[所有三个python模块都在同一台机器上。 connection.py
作为独立脚本执行,并且首先执行。每当需要时,都会在项目的其他模块中多次调用function()
中的tasks.py
方法,因此,我无法在此方法中实例化Client
类。全局变量不起作用。
在Java中,我们可以创建全局静态变量,并在整个项目中对其进行访问。我们如何在python中做到这一点?
我可以想到的方法,但不确定是否可以在python中完成:
对于有兴趣知道为什么要这样做的人,请see this question。它说明了完整的系统设计以及所涉及的各个组件。
我也欢迎需要更改代码结构的建议。
multiprocessing
提供了执行此操作所需的所有工具。
connection.py
multiprocessing
tasks.py
from multiprocessing.managers import BaseManager
from client import Client()
client = Client()
class ClientManager(BaseManager): pass
ClientManager.register('get_client', callable=lambda: client)
manager = ClientManager(address=('', 50000), authkey='abracadabra')
server = manager.get_server()
server.serve_forever()
我没有使用django的经验,但是如果它们是从同一脚本执行的,则可以使Client单身,或者可以在init。py中声明Client,然后将其导入到任何需要的地方。
如果您选择单身人士,则可以为此做一个装饰器:
from multiprocessing.managers import BaseManager
class ClientManager(BaseManager): pass
ClientManager.register('get_client')
manager = ClientManager(address=('localhost', 50000), authkey='abracadabra')
manager.connect()
client = manager.get_client()
@app.task
def function():
message = "Message to send to the server using the established connection"
client.send_message(message)
然后您将定义:
def singleton(cls):
instances = {}
def get_instance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return get_instance
这就是我所建议的所有简短描述。也许可以尝试更好地解释一切如何运行或涉及的部分。
Python具有类属性(实例之间共享的属性)和类方法(作用于类本身的方法)。两者在类和实例上都是可读的。
# client.py
@singleton
class Client:
def __init__(self):
# code for opening a persistent connection and saving the connection client in a class variable
...
self.client = <connection client>
def get_connection_client(self):
return self.client
现在我不确定这是否是解决您问题的最佳解决方案。
如果connection.py是导入的tasks.py,则可以在tasks.py中进行:
# client.py
class Client(object):
_client = None
@classmethod
def connect(cls):
# dont do anything if already connected
if cls._client is None:
return
# code for opening a persistent connection and saving the connection client in a class variable
...
cls._client = <connection client>
@classmethod
def get_connection_client(cls):
return cls._client
def __init__(self):
# make sure we try to have a connection on initialisation
self.connect()
BaseManager也是一个答案,但它在localhost上使用套接字网络,如果您尚未使用多重处理,则不是访问变量的好方法。我的意思是,如果需要使用多重处理,则应该使用BaseManager。但是,如果您不需要多重处理,则不是使用多重处理的好选择。我的代码只是从中获取connection.py中“ client”变量的指针口译员。
此外,如果您想使用多重处理,我的代码将无法正常工作,因为不同进程中的解释器是不同的。