据我所知,Python记录器不能直接实例化,因为文档建议:
请注意,记录器永远不会 直接实例化,但始终 通过模块级功能
logging.getLogger(name)
..这是合理的,因为你需要不为每个类/模块创建记录器对象,因为有better alternative。
但是,在某些情况下,我希望创建一个记录器对象,并将一个文件专门附加到它,以便将某些特定于应用程序的输出记录到该文件中;然后关闭日志文件。
例如,我有一个程序可以在PyPI中构建所有包。所以基本上假设每个包都有一个for
循环。在循环内部,我想“创建”一个记录器,附加一个文件处理程序(例如:/var/logs/pypi/django/20090302_1324.build.log并发送python setup.py build
的输出(以及其他内容)这个日志文件。一旦完成,我想关闭/销毁记录器,continue
以类似的方式构建其他包。
所以你看到..调用logging.getLogger
的正常Pythonic方式在这里不适用。需要创建临时记录器对象。
目前,我通过将文件名本身作为记录器名称传递来实现此目的:
>>> packagelog = logging.getLogger('/var/..../..34.log')
>>> # attach handler, etc..
我想问......有更好的方法吗?
答案 0 :(得分:4)
您可以使用一个记录器和多个处理程序,而不是许多记录器。例如:
log = logging.getLogger(name)
while some_condition:
try:
handler = make_handler(filename)
log.addHandler(handler)
# do something and log
finally:
log.removeHandler(handler)
handler.close()
答案 1 :(得分:1)
这里有两个问题:
对于第1点,我会同意ars
的答案:他只关注使用多个处理程序和一个记录器。他的格式有点混乱,所以我将在下面重申:
logger = logging.getLogger("pypibuild")
now_as_string = datetime.datetime.utcnow().strftime("%Y%m%d_%H%M")
for package in get_pypi_packages():
fn = '/var/logs/pypi/%s/%s.log' % (package, now_as_string)
h = logging.FileHandler(fn, 'w')
logger.addHandler(h)
perform_build(package)
logger.removeHandler(h)
h.close()
关于第2点,perform_build()
步骤,为简单起见,我假设我们不需要担心多核环境。然后,subprocess
模块就是你的朋友。在下面的代码片段中,我省略了错误处理,花哨格式化和其他一些细节,但它应该给你一个公平的想法。
def perform_build(package):
logger.debug("Starting build for package %r", package)
command_line = compute_command_line_for_package(package)
process = subprocess.Popen(command_line, shell=True,
stdin=PIPE, stdout=PIPE, stderr=PIPE)
stdout, stderr = process.communicate()
logger.debug("Build stdout contents: %r", stdout)
logger.debug("Build stderr contents: %r", stderr)
logger.debug("Finished build for package %r", package)
就是这样。
答案 2 :(得分:0)
假设你正在调用setup.py build
作为子进程,我认为你真的只想要输出重定向,你可以通过子进程调用获得它。
from subprocess import Popen
with open('/var/logs/pypi/django/%s.build.log' % time_str, 'w') as fh:
Popen('python setup.py build'.split(), stdout=fh, stderr=fh).communicate()
如果您将setup.py build
作为Python子例程调用(即导入该模块并调用它的主例程),那么您可以尝试将另一个logging.Handler
(FileHandler
)添加到记录器如果存在这样的记录器,则在该模块中。
<强>更新强>
根据回答评论,听起来您只想add a new FileHandler到当前模块的记录器,然后将其记录到那个,然后remove it from the logger later on。这更像是你在寻找什么?