我有一个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。它解释了完整的系统设计和涉及的各种组件。
我愿意接受需要改变代码结构的建议。
答案 0 :(得分:2)
multiprocessing
提供了执行此操作所需的所有工具。
<强> connection.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()
<强> tasks.py 强>
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)
答案 1 :(得分:0)
我没有使用django的经验,但是如果它们是从同一个脚本执行的,那么你可以让客户端成为单例,或者可以在 init .py中声明客户端,然后将其导入到任何地方你需要它。
如果你选择单身人士,你可以为此做一个装饰:
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
然后你会定义:
# 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
这就是我所能提出的所有内容。也许试着更好地解释一切运行方式或涉及的部分。
答案 2 :(得分:0)
Python具有类属性(在实例之间共享的属性)和类方法(作用于类本身的方法)。两者在类和实例上都是可读的。
# 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()
现在我不确定这是解决问题的最佳方法。
答案 3 :(得分:0)
如果connection.py正在导入tasks.py ,则可以在tasks.py中进行:
import __main__ # connection.py
main_globals = __main__.__dict__ # this "is" what you getting in connection.py when you write globals()
client = main_globals["client"] # this client has the same id with client in connection.py
BaseManager也是一个答案,但它在localhost上使用套接字网络,如果您尚未使用多处理程序,则它不是访问变量的好方法。我的意思是,如果需要使用多重处理,则应该使用BaseManager。但是,如果您不需要多重处理,则不是使用多重处理的好选择。我的代码只是从中获取connection.py中“ client”变量的指针 解释器。
如果您要使用多重处理,我的代码将无法正常工作,因为不同进程中的解释器不同。
答案 4 :(得分:-1)
从文件中读取时使用pickle
。