如何初始化一个python对象并在其他模块间共享?

2021-06-15 00:18:44 发布

您现在位置:Python中文网/ 问答频道 /正文

对我来说,我发现我的python转换非常令人沮丧。我正在尝试做的一件事是从配置字典初始化一个类的单个实例,然后在其他模块中访问该类。

我所面临的问题/我所采取的方法没有得到解决,我希望有人能用正确的“Python式”方法。

首先,我的应用程序可以初始化为twistd插件的一部分,或者作为独立脚本。

import resource
class App(object):
  _config = None
  _someotherobject = None
  def __init__(self, config):
    self._config = config
    ....

def main():
  global myapp
  myapp = App({}) # Could use help here, how to pass config to it

myapp = None #Global doesnt work as I expect, it doesnt modify this instance, stays as None
if __name__ == '__main__':
  main()


#-----------resource.py
class Foo(object):
  def foo(self):
    app.myapp.somefunction() #NoneType object has no attribute

我已经验证了app对象是在启动另一个模块中的代码之前创建的。我只是不明白为什么模块中的“global”实例实际上没有达到我所期望的效果,也不明白如何从另一个模块引用该实例。

----编辑------ 为了澄清几点,脚本使用python app.py调用 py引用了一个名为resources.py的模块,它是一堆类定义。在某些类中,当执行时,它们引用app.myapp的“singleton”实例。

3条回答
网友
1楼 ·

你最大的问题是索塔普提到的那个。如果实际上没有将app.py作为顶级脚本运行,则没有任何代码调用app.main(),因此没有初始化全局脚本的功能。

除此之外,“如何从另一个模块引用实例”非常简单,如果您知道一件简单的事情:

在Python中,globals是有名称空间的。

更具体地说,在其他模块中,只需import app,然后以app.myapp的形式访问全局。

正如sotapme所解释的,使用__name__ == '__main__'技巧意味着您可以随心所欲地import app多次,而不必每次都运行main()函数。

特别是,运行此命令时:

python app.py

Python解释器将加载app.py,其__name__设置为'__main__',因此if语句将触发,这将导致(模块级)全局变量myapp设置为App({})

现在,当resource.py执行import app时,它的__name__将设置为app,因此if语句将而不是触发器,因此您将构造一个新的App并替换全局触发器。从resource.py中的代码中,您可以使用app.myapp,并且您将访问app.py中的代码视为myapp的同一对象。


您还需要帮助才能将配置传递给App构造函数。我不知道你有什么问题。您正在传递一个空的dict作为配置。如果您有不同的dict要传递,请使用它。而不是这个:

myapp = App({}) # Could use help here, how to pass config to it

执行以下操作:

myapp = App(configdict)

如果你的问题是知道如何获取信息,那取决于信息的来源。

如果您试图解析用户可编辑的配置文件,^{}模块对传统的.ini样式文件很好,并且文档中有一些链接,可以解释如何处理其他一些流行格式。

如果您试图从命令行建立配置信息,请参见^{}

如果您希望允许环境变量与上述任何一个变量交互(例如,MYAPP_CONFIG可能会告诉您的configparser代码加载一个与普通配置文件不同的配置文件,或者MYAPP_CACHE_DIR可能会为--cachedir的命令行参数提供不同的默认值,argparse),您将获得^{}中的值,但是你必须自己写代码来处理它们。

网友
2楼 ·

要稍微清理一下,下面是一个例子:

class App:
    _config = None
    _someotherobject = None

def __init__(self, config):
    self._config = config

def main():
  myapp = App(config) # pass a config object to App

if  __name__ =='__main__':main()

从另一个应用程序中,您必须执行以下操作:

from first_app import App

myapp = App(config)
网友
3楼 ·

您的main将仅作为独立脚本调用,而不是从其他模块导入时调用。

if __name__ == '__main__':
  main()

是使模块可以从命令行运行的技巧。

为了证明这一点

import app
app.main()

然后运行你的代码。

一旦初始化了它app就会变成一个单例,任何其他导入它的模块都会得到该初始化版本。

我有一个类似的问题,我不想访问app,但希望模块能够说app = MyApp(),并且仍然共享相同的数据(我忘记了为什么我想要它,但这可能与希望它在首次使用时初始化有关)

我最终使用了Borg而不是单例。

相关问题