简体   繁体   English

访问在脚本的主模块中定义的 python 类变量

[英]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 中完成:

  • Save this variable in a common file such that it is accessible in other modules in my project?将此变量保存在一个公共文件中,以便在我的项目中的其他模块中可以访问它?
  • Save this client as a setting in either django or celery and access this setting in the required module?将此客户端保存为 django 或 celery 中的设置并在所需模块中访问此设置?
  • Based on suggestions by sebastian, another way is to share variables between running processes.根据 sebastian 的建议,另一种方法是在正在运行的进程之间共享变量。 I essentially want to do that.我基本上想这样做。 How do I do this 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.

相关问题 如何访问在main函数中导入的模块中的变量,该模块在python中的main()中定义 - How to access a variable in a module which is being imported in the main function and which is defined inside main() in python 父级访问在Python中的子级中定义的类变量? - Parent accessing class variable defined in child in Python? 帮助访问 Python function 中的模块变量? - Help with accessing module variable inside Python function? __main__ 中定义的 class 变量,可在不同模块中访问 - variable for class defined in __main__ with access in different module Python 未定义全局变量 - 在内部声明 Class - Python Global Variable Not Defined - Declared inside Class 在Python中,访问变量在main中从另一个模块定义 - In Python, access variable defined in main from another module 在主脚本中定义的全局变量不能由在不同模块中定义的函数访问 - global variable defined in main script can't be accessed by a function defined in a different module 从 python class 中的另一个方法访问在方法内部创建的变量 - accessing a variable created inside a method from another method in a python class 在类的方法内部访问变量 - Accessing a variable inside the method of a class 如何继承python 3中类的__init__方法内部定义的变量 - How to inherit a variable defined inside __init__ method of a class in python 3
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM