[英]Accessing python class variable defined inside the main module of a script
I have a django project that uses celery for async task processing.我有一个使用 celery 进行异步任务处理的 django 项目。 I am using python 2.7.
我正在使用 python 2.7。
I have a class in a module client.py
in my django project:我的 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
...
This class needs to be instantiated only once to create one persistent connection to a remote server .此类只需实例化一次即可创建到远程服务器的持久连接。
I run a script connection.py
that runs indefinitely:我运行一个无限期运行的脚本
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
...
I need to access the variable client
from another module tasks.py
(needed for celery).我需要从另一个模块
tasks.py
访问变量client
(芹菜需要)。
# 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)
All the three python modules are on the same machine.所有三个 python 模块都在同一台机器上。 The
connection.py
is executed as a standalone script and is executed first. connection.py
作为独立脚本执行并首先执行。 The method function()
in tasks.py
is called multiple times across other modules of the project whenever required, thus, I can't instantiate the Client
class inside this method.需要时,
tasks.py
的方法function()
在项目的其他模块中被多次调用,因此,我无法在此方法中实例化Client
类。 Global variables don't work.全局变量不起作用。
In java, we can create global static variable and access it throughout the project.在java中,我们可以创建全局静态变量并在整个项目中访问它。 How do we do this in python?
我们如何在python中做到这一点?
Approaches I can think of but not sure if they can be done in python:我能想到的方法,但不确定它们是否可以在 python 中完成:
For those interested to know why this is required, please see this question .对于那些有兴趣知道为什么需要这样做的人,请参阅此问题。 It explains the complete system design and the various components involved.
它解释了完整的系统设计和涉及的各种组件。
I am open to suggestions that needs a change in the code structure as well.我也愿意接受需要更改代码结构的建议。
multiprocessing
provides all the tools you need to do this.multiprocessing
提供了您执行此操作所需的所有工具。
connection.py连接.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任务.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)
I dont have experience working with django, but if they are executed from the same script you could make the Client a singleton, or maybe declaring the Client in the init .py and then import it wherever you need it.我没有使用 django 的经验,但是如果它们是从同一个脚本执行的,您可以使客户端成为单例,或者可能在init .py 中声明客户端,然后将其导入到您需要的任何位置。
If you go for the singleton, you can make a decorator for that:如果你选择单例,你可以为此做一个装饰器:
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
Then you would define:然后你会定义:
# 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
Thats all I can suggest with the little description you have given.这就是我可以通过您给出的小说明提出的所有建议。 Maybe try to explain a little better how everything is run or the parts that are involved.
也许尝试更好地解释一切如何运行或所涉及的部分。
Python has class attributes (attributes that are shared amongst instances) and class methods (methods that act on the class itself). Python 具有类属性(在实例之间共享的属性)和类方法(作用于类本身的方法)。 Both are readable on either the class and an instance.
两者在类和实例上都是可读的。
# 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()
Now I'm not sure this is the best solution to your problem.现在我不确定这是您问题的最佳解决方案。
If connection.py is importing tasks.py , you can do it in your tasks.py:如果 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 is also an answer but it uses socket networking on localhost and it is not a good way of accessing a variable if you dont already using multiprocessing. BaseManager 也是一个答案,但它在本地主机上使用套接字网络,如果您还没有使用多处理,它不是访问变量的好方法。 I mean if you need to use multiprocessing, you should use BaseManager.
我的意思是如果你需要使用多处理,你应该使用 BaseManager。 But if you dont need multiprocessing, it is not a good option to use multiprocessing.
但是如果你不需要多处理,那么使用多处理不是一个好的选择。 My code is just taking pointer of "client" variable in connection.py from interpreter.
我的代码只是从解释器中获取 connection.py 中“客户端”变量的指针。
Also if you want to use multiprocessing, my code won't work because the interpreters in different processes are different.此外,如果您想使用多处理,我的代码将无法工作,因为不同进程中的解释器不同。
You can use pickle. 您可以使用泡菜。 For example pickle.dump function converts any python object to byte.
例如pickle.dump函数将任何python对象转换为字节。
从文件中读取时使用pickle
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.