2

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

我面临的问题/我采取的方法没有解决,我希望有人可以引导正确的“pythonic”方法。

首先,我的应用程序可以作为一个 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 对象是在另一个模块中的代码启动之前创建的。我只是无法弄清楚为什么模块中的“全局”实例实际上并没有达到我的预期,也对如何从另一个模块引用该实例感到困惑。

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

4

3 回答 3

3

Your main will only ever be called as a standalone script not when imported from another module.

if __name__ == '__main__':
  main()

Is the trick to make your modules runnable from the command line.

To prove it

import app
app.main()

Then run your piece of code.

Once you've initialised it app becomes like a singleton, any other module importing it will get that initialised version.

I had a similar problem where I didn't want to access app but wanted modules to be able to say app = MyApp() and still share the same data ( I forget why I wanted it but it might have had to do with wanting it initialised on first use)

I ended up using a Borg instead of a Singleton.

于 2013-02-19T21:10:04.013 回答
0

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

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

在 Python 中,全局变量是命名空间的。

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

正如 sotapme 解释的那样,使用该__name__ == '__main__'技巧意味着您可以import app根据需要多次运行,而无需main()每次都运行该功能。

特别是,当您运行此命令时:

python app.py

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

现在,什么resource.py时候 an import app__name__它将被设置为app,因此该if语句不会触发,因此您将构造一个 newApp并替换全局。从 中的代码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)

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

如果您尝试解析用户可编辑的配置文件,则该configparser模块适用于传统的 .ini 样式文件,并且文档具有解释如何处理其他一些流行格式的链接。

如果您尝试从命令行构建配置信息,请参阅argparse.

如果您想允许环境变量与上述任何一个交互(例如,aMYAPP_CONFIG可能会告诉您的configparser代码加载与正常情况不同的配置文件,或者 a可能为 的命令行参数MYAPP_CACHE_DIR提供不同的默认值),您将获得中的值,但必须编写自己的代码才能对它们执行任何操作。--cachedirargparseos.environ

于 2013-02-19T21:34:36.213 回答
0

为了稍微清理一下,这里有一个例子:

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)
于 2013-02-19T21:46:08.787 回答