在__init__.py中检测软件包是否作为程序运行

发布于 2025-01-30 00:43:27 字数 1384 浏览 6 评论 0原文

我有一个带有__ Int __. py的Python软件包,该软件包会导入某些内容作为软件包API。

# __init__.py

from .mymodule import MyClass
# ...

我还希望能够将软件包用作命令行应用程序,如python -m mypackage,所以我有一个__ main __. py用于此目的:

# __main__.py

if __name__ == '__main__':
    from .main import main
    main()

到目前为止,一切都很好。问题是,当包裹以这样的程序运行时,我希望能够在导入任何一个子模型之前做一些事情 - 即在某些第三方依赖关系之前更改某些环境变量已加载。

我不知道该怎么做,至少不是以合理的方式做到这一点。理想情况下,我想做类似的事情:

# __init__.py

def thePackageIsRunningAsAnApplication():
    # ???

def prepareEnvironment():
    # ...

if thePackageIsRunningAsAnApplication():
    prepareEnvironment()

from .mymodule import MyClass
# ...

问题是我认为可以实现thepackageisrunningasanapplication()。通常的__ name __ =='__ main __'在这里不起作用,因为正在运行的主模块是__ main __. py,而不是__ INT __ INT __。py。实际上,我更喜欢在__ Main __. py中定义并运行准备,但是我不知道如何在内部模块加载之前将其运行。代码> __ INIT __。py 。

I 可能(不确定,实际上)通过在模块上懒惰地加载依赖性或以某种方式延迟内部模块加载或其他内容来解决它,但是我宁愿避免为此做这样的事情。

编辑:对此进行更多思考,懒惰的加载可能也无法正常工作。在示例中,myClass是一个类,而不是子模块,因此我不能懒惰地加载它。此外,myClass恰好是从我提到的第三方依赖性的类继承的,因此我什至无法在不加载的情况下定义它。

I have a Python package with an __init__.py that imports some things to be exposed as the package API.

# __init__.py

from .mymodule import MyClass
# ...

I also want to be able to use the package as a command-line application, as in python -m mypackage, so I have a __main__.py file for that purpose:

# __main__.py

if __name__ == '__main__':
    from .main import main
    main()

So far so good. The problem is that, when the package is run as a program like this, I want to be able to do some stuff before importing any of the submodules - namely changing some environment variables before some third-party dependencies are loaded.

I do not know how to do this, at least not in a reasonable way. Ideally, I would like to do something like:

# __init__.py

def thePackageIsRunningAsAnApplication():
    # ???

def prepareEnvironment():
    # ...

if thePackageIsRunningAsAnApplication():
    prepareEnvironment()

from .mymodule import MyClass
# ...

The problem is I don't think thePackageIsRunningAsAnApplication() can be implemented. The usual __name__ == '__main__' does not work here, because the main module being run is __main__.py, not __init__.py. In fact, I would prefer to define and run prepareEnvironment within __main__.py, but I don't know how to get that to run before the inner modules are loaded by __init__.py.

I might (not sure, actually) work around it by lazily loading dependencies on my module, or somehow delaying the internal module loading or something, but I would prefer to avoid doing something like that just for this.

EDIT: Thinking more about it, lazy loading probably would not work either. In the example, MyClass is, well, a class, not a submodule, so I cannot lazily load it. Moreover, MyClass happens to inherit from a class from that third-party dependency I was mentioning, so I cannot even define it without loading it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

你丑哭了我 2025-02-06 00:43:27

添加一个单独的输入点以作为脚本运行代码,而不是使用main __。py,只能在软件包的__ init __ __ Init __ Init______________________________。 .py已满载。

一个简单的脚本,例如位于顶级的run_mypackage.py,可以包含环境变量的代码,然后可以在之后导入并运行包。

def prepare_environment():
    ...

if __name__ == "__main__":
    prepare_environment()            # adjust the environment firstt

    from mypackage.main import main  # then load the package afterwards
    main()

It might make sense to add a separate entry point for running your code as a script, rather than using __main__.py, which as you've noticed, can only be run after the package's __init__.py is fully loaded.

A simple script like run_mypackage.py located at the top level could contain the environment variable tweaking code, and then could import and run the package afterwards.

def prepare_environment():
    ...

if __name__ == "__main__":
    prepare_environment()            # adjust the environment firstt

    from mypackage.main import main  # then load the package afterwards
    main()
溺孤伤于心 2025-02-06 00:43:27

不能100%确定您想明智地做什么。

AFAIK在进口之前没有预处理器步骤。
在其他语言中,通常还有编译器标志,可以在进口之前阅读,但我不知道Python是否可以使用。

我可能的解决方案可以解决Import之前的明智问题,可能是要在其他子模型之前进行单独的软件包(当然,您需要某种切换才能在您打电话/使用该软件包通常的外部方式时不运行它) 。
在软件包的导入时,整个软件包要运行(如果没有 name ==' main '部分),可以在其他模块为importet之前使用。
但是,如果您是指在以不同的方式调用程序时解决某些环境问题,我认为没有任何歧义的多IMPOTH PATHS解决方案。
如果您的软件包被当地保存,则有相对的导入路径,但我认为它们不能以这种方式使用。
不过会是一些有趣的实验。

Not 100% sure what you want to do pre-import wise.

Afaik there is no preprocessor step before imports.
In other languages than python there usually are compiler flags which can be read before imports are done but i don't know if python has those to.

I possible solution to do stuff pre-import wise could be to have a seperate package that is imported before your other submodules (ofcourse you would need some kind of switch to not have it run when you call/use the package the usual external way).
At import of the package the whole package is run (if there is no name == 'main' part) which can be used to do stuff before the other modules are importet.
But if you mean solving some environment issues when your programm is called on the different way i think there is no way for having multi-importpath resolution without ambiguity.
There are relative import paths if your package is locally saved but i don't think they can be used that way.
Would be some interesting experiment though.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文