如何从其他模块访问当前执行模块的属性?

2024-04-20 01:55:20 发布

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

我有几个“应用程序”模块(由主应用程序启动) 以及一个实用模块,具有一些功能:

my_utility/
    ├── __init__.py
    └── __main__.py
apps/
    ├── app1/
    │   ├── __init__.py
    │   └── __main__.py
    ├── app2/
    │   ├── __init__.py
    │   └── __main__.py
    ...
main_app.py

应用程序的启动方式如下(由主应用程序启动):

python3 -m <app-name>

我需要提供一些关于每个应用程序的元信息(与模块相关),这些应用程序可以被main_app和应用程序本身读取:

应用程序/app1/\uu init\uuuuuuuuuuuuy.py

meta_info = {'min_platform_version': '1.0',
             'logger_name': 'mm1'}

。。。像这样使用:

应用程序/app1/\uuu main\uuuuuuuuuuuuuuuuuuuuuuuuu.py

from my_utility import handle_meta_info
# does something with meta_info (checking, etc.)
handle_meta_info()

主_应用程序类型

mod = importlib.import_module('app1')
meta_inf = getattr(mod, 'meta_info')
do_something(meta_inf)

问题

我不知道如何从应用程序中访问meta_info。我知道我能 import模块本身和访问meta_info

应用程序/app1/\uuu main\uuuuuuuuuuuuuuuuuuuuuuuuu.py

import app1
do_something(app1.meta_info)

但这只有在我知道模块名称的情况下才有可能。从另一个模块内部-例如my_utility我不知道如何访问首先启动的模块(或者它的名称)。你知道吗

我的\u实用程序/\uu主\uuuuuuuuu.py

def handle_meta_info():
    import MAIN_MODULE        <-- don't know, what to import here
    do_something(MAIN_MODULE.meta_info)

换句话说

我不知道如何从应用程序的进程中访问meta_info(通过python3 -m <name>启动),但是从另一个不知道已启动的“根”模块名称的模块中访问

方法

  • 在调用meta-info函数时始终提供模块名(错误,因为它冗长且冗余)

    from my_utility import handle_meta_info
    handle_meta_info('app1')
    
  • meta_info添加到__builtins__(通常不利于污染全球空间)

  • 分析命令行(丑陋)

  • 分析import my_utility(危险,丑陋)

我想看看解决办法

如果能够访问“main”模块的全局空间或者知道它的名称(要导入),那就太好了

我的\u实用程序/\uu主\uuuuuuuuu.py

def handle_meta_info():
    do_something(__main_module__.meta_info)

或者

def handle_meta_info():
    if process_has_been_started_as_module():
        mod = importlib.import_module(name_of_main_module())
        meta_inf = getattr(mod, 'meta_info')
        do_something(meta_inf)

有什么想法吗?你知道吗

我当前(血腥的)解决方案:

my_utility内部,我使用psutil获取模块启动时使用的命令行(为什么不sys.argvBecause)。在这里我提取模块名。通过这种方式,我将所需的元信息附加到my_utility(因此我只需加载一次)。你知道吗

我的\u实用程序/\uu初始化\uuuuuuuuuuy.py

def __get_executed_modules_meta_info__() -> dict:
    def get_executed_module_name()
        from psutil import Process
        from os import getpid
        _cmdline = Process(getpid()).cmdline
        try:
            # normal case: app has been started via 'python3 -m <app>'
            return _cmdline[_cmdline.index('-m') + 1]
        except ValueError:
            return None
    from importlib import import_module
    try:
        _main_module = import_module(get_module_name())
        return import_module(get_executed_module_name()).meta_info
    except AttributeError:
        return {}

__executed_modules_meta_info__ = __get_executed_modules_meta_info__()

Tags: 模块namepyimportinfoapp应用程序main