在python中,如果在父进程中配置了记录器,那么子进程是否也会获得该记录器?更清楚的是,在我的应用程序中,我通过执行logger = logging.getlogger()
并为其添加处理程序来为父进程配置根记录器。现在,当一个子进程被分叉并且它确实
logger = logging.getlogger()
logger.info("dfsdf")
然后根据父级的根记录器处理所有日志。我没有为孩子配置根记录器。这怎么可能?它们是两个不同的过程,那么它们如何具有相同的记录器呢?
答案 0 :(得分:4)
当你分叉一个进程时,它'继承'父进程内存,包括记录器配置。
fork操作为子项创建单独的地址空间。子进程具有父进程的所有内存段的精确副本,但是如果实现了写时复制语义,则可能不会分配实际的物理内存(即,两个进程可能共享相同的物理内存段一段时间) 。父进程和子进程都拥有相同的代码段,但彼此独立地执行。
这不是Python独有的;对于任何分叉的UNIX进程,无论是在C,Perl还是Python中实现,都会发生这种情况。
multiprocessing
module使用它(在支持它的平台上)快速启动新进程。
请注意,继承记录器可能会导致竞争条件; logging
模块只知道线程安全性;它使用线程锁来序列化对处理程序的访问,但该锁不是跨进程共享的(子进程中的所有内容都是副本,而不是同一个对象)。
这意味着当您同时记录来自父级和子级的消息时,日志条目最终会混合在一起,因为操作系统在将日志条目写入文件时在两个进程之间切换。
答案 1 :(得分:3)
有两件事可能让你感到困惑。
“相同的记录器对象。”当然,对象并不相同,就像子进程中的所有对象与父进程中的对象不同。子进程是其父进程的完整副本,具有单独的地址空间。这意味着他们不共享任何记忆。如果对象位于父进程中的某个内存地址,则fork后子进程将具有位于同一地址的相同对象。但是,地址位于不同的地址空间中,不共享存储器,并且在完成分叉之后对象彼此不相关。所以,对你的问题的简短回答是:对象不一样。
在fork完成之前,logger对象可能打开了一个文件。子进程继承了打开文件。这意味着这两个进程有一个文件的两个文件句柄。这是同步问题。
UPD:我已经查看了Python 2.7安装中的日志记录模块源代码。它使用threading.RLock
来同步日志访问。这意味着您无法在父进程和子进程中安全地使用相同的日志文件。您必须关心具有不同日志的子进程和父进程。它是守护程序吗?如果是,通常父进程不需要太多日志记录,并且可能使用单独的记录器。