我有一个小的日志包装模块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,则可能不正确。)
这样的事情可能吗?
答案 0 :(得分:3)
就个人而言,我会坚持你所拥有的代码;不那么神奇,更清晰。
您可以使用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()
的调用是在装饰器函数内部,理论上您可以访问一组不同的全局变量(装饰器定义的模块),但在绝大多数情况下,&# 39; d正是您想要使用的模块名称。通过moduleName
可选,您可以明确为角落案例设置它。
将Python程序打包到可执行文件(使用py2exe
或类似文件)会影响文件名(特别是对于主脚本),但模块名称应保持不变。
答案 1 :(得分:1)
我只想补充已经很好的答案:
在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
这有助于保持会话清洁。