Python: 导入带参数的模块?

Python: importing a module with parameters?

我有一个小的日志包装模块,test.logging:

import logging

debuglog = "debug.log"
f = open(debuglog, 'w') # truncate the file
f.close()

logger = logging.getLogger('test')
logger.setLevel(logging.INFO)

formatter = logging.Formatter(
    '%(asctime)s %(name)s %(levelname)s: %(filename)s:%(lineno)d: %(message)s')

fh = logging.FileHandler(debuglog)
fh.setLevel(logging.DEBUG)
fh.setFormatter(formatter)
logger.addHandler(fh)

def get(moduleName):
    return logging.getLogger("test." + moduleName)

和一些使用它的模块,例如test.example:

import test.logging
logger = test.logging.get(__name__)

logger.info("This is an info message from test.example")

我想知道是否有办法减少 test 的每个子模块中出现的前两行的重复。我想做类似的事情:

from test.logging get(__name__) as logger
logger.info("This is an info message from test.example")

或者更好,如果我也可以省略 __name__ 并让 get() 自动确定模块名称。 (据我所知,inspect 模块可以做到这一点,但如果调用者被装饰或程序被编译为 EXE,则可能不正确。)

这样的事情可能吗?

就个人而言,我会坚持使用您的代码;更少魔法,更清晰。

您可以通过访问堆栈中的帧来访问调用代码的模块名称,使用 sys._getframe():

import sys

def get(moduleName=None):
    if moduleName is None:
        caller = sys._getframe(1)
        moduleName = caller.f_globals['__name__']
    return logging.getLogger("test." + moduleName)

使模块名称可选:

from test import logging
logger = logging.get()

是的,如果您对 logging.get() 的调用是在装饰器函数内,理论上您可以访问一组不同的全局变量(定义装饰器的模块的全局变量),但在绝大多数情况下那就是您要使用的模块名称。通过使 moduleName 可选 您可以保留为极端情况明确设置它的可能性。

将 Python 程序打包为可执行文件(使用 py2exe 或类似文件)会影响文件名(尤其是主脚本),但模块名称应保持不变。

我只是想补充一下已经很棒的答案:

在python中,有一个字典保存着你和系统在会话中定义的每一个该死的变量。它存储在 globals() 中。如果您键入 globals(),您将获得已定义的每个变量和对象。例如:

Python 2.7.6 (v2.7.6:3a1db0d2747e, Nov 10 2013, 00:42:54) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "copyright", "credits" or "license()" for more information.
>>> globals()
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', 
'__doc__': None, '__package__': None}
>>> 

每当您访问变量或对象(例如文件,甚至模块本身)时,python 都会在此字典中查找它。 import 语句本质上是获取模块并将其放入此字典中。你可以做一些漂亮的事情。除了无聊的 import thisimport that,您还可以:

import this.that
from this import that

这有助于保持会话干净。