我想知道在特殊情况下构建我的日志的最佳方法是什么。
我有一系列python服务,使用相同的python文件与HW进行通信(例如com.py)。我在这个模块中实现了日志记录,我希望它与调用模块的主服务相关(关联)。
我应该如何构建记录器逻辑,以便如果我有:
日志记录转到文件 main_serv_1.log
日志记录转到文件 main_serv_2.log
在没有任何东西的情况下,这种情况下的最佳做法是什么?
有没有办法知道导入com.py的文件,以便我能够在com.py中使用此信息来调整日志记录到调用者?
答案 0 :(得分:1)
根据我的经验,对于这种情况,最干净,最容易实施的策略是将记录器传递给执行记录的代码。
因此,为每个要登录其他文件的服务创建一个记录器,并将该记录器传递给通信模块中的代码。您可以使用__name__
获取当前模块的名称(实际模块名称,不带.py
扩展名)。
在下面的示例中,我实现了在没有传入记录器的情况下的回退。
<强> com.py
强>
from log import setup_logger
class Communicator(object):
def __init__(self, logger=None):
if logger is None:
logger = setup_logger(__name__)
self.log = logger
def send(self, data):
self.log.info('Sending %s bytes of data' % len(data))
<强> svc_foo.py
强>
from com import Communicator
from log import setup_logger
logger = setup_logger(__name__)
def foo():
c = Communicator(logger)
c.send('foo')
<强> svc_bar.py
强>
from com import Communicator
from log import setup_logger
logger = setup_logger(__name__)
def bar():
c = Communicator(logger)
c.send('bar')
<强> log.py
强>
from logging import FileHandler
import logging
def setup_logger(name):
logger = logging.getLogger(name)
handler = FileHandler('%s.log' % name)
logger.addHandler(handler)
return logger
<强> main.py
强>
from svc_bar import bar
from svc_foo import foo
import logging
# Add a StreamHandler for the root logger, so we get some console output in
# addition to file logging (for easy of testing). Also set the level for
# the root level to INFO so our messages don't get filtered.
logging.basicConfig(level=logging.INFO)
foo()
bar()
因此,当您执行python main.py
时,这就是您将获得的:
在控制台上:
INFO:svc_foo:Sending 3 bytes of data
INFO:svc_bar:Sending 3 bytes of data
svc_foo.log
和svc_bar.log
每行都有一行
Sending 3 bytes of data
如果Communicator
类的客户端使用它而不传入记录器,则日志输出将以com.log
(后备)结束。
答案 1 :(得分:0)
我看到了几个选项:
选项1
使用__file__
。 __file__
是加载模块的文件的路径名(doc)。根据您的结构,您应该能够通过执行os.path.split()
来识别模块:
如果文件夹结构是
+- module1
| +- __init__.py
| +- main.py
+- module2
+- __init__.py
+- main.py
您应该能够使用 main.py 中的代码获取模块名称:
def get_name():
module_name = os.path.split(__file__)[-2]
return module_name
这不完全是DRY,因为在 main.py 中需要相同的代码。参考here。
选项2
更清洁的是打开2个终端窗口并使用环境变量。例如。您可以在一个终端中将MOD_LOG_NAME
定义为MOD_LOG_NAME="main_service_1"
,在另一个终端中定义MOD_LOG_NAME="main_service_2"
。然后,在你的python代码中,你可以使用类似的东西:
import os
LOG_PATH_NAME os.environ['MOD_LOG_NAME']
更新(因为问题有所改进)
一旦建立了不同的名称,您所要做的就是配置记录器:
import logging
logging.basicConfig(filename=LOG_PATH_NAME,level=logging.DEBUG)
(或get_name()
)并运行程序。