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 this
和 import that
,您还可以:
import this.that
from this import that
这有助于保持会话干净。
我有一个小的日志包装模块,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 this
和 import that
,您还可以:
import this.that
from this import that
这有助于保持会话干净。