我有一个可能长时间运行的程序,当前有 4 个进程,但可以配置为有更多进程。我研究过从多个进程记录 http://docs.python.org/howto/logging-cookbook.html#logging-to-a-single-file-from-multiple-processes使用Python的logging
并正在使用讨论的 SocketHandler 方法here http://docs.python.org/howto/logging-cookbook.html#sending-and-receiving-logging-events-across-a-network。我从来没有遇到过使用单个记录器(没有套接字)的任何问题,但从我读到的内容来看,我被告知它最终会意外失败。据我了解,当您尝试同时写入同一个文件时,未知会发生什么。我的代码基本上执行以下操作:
import logging
log = logging.getLogger(__name__)
def monitor(...):
# Spawn child processes with os.fork()
# os.wait() and act accordingly
def main():
log_server_pid = os.fork()
if log_server_pid == 0:
# Create a LogRecordSocketServer (daemon)
...
sys.exit(0)
# Add SocketHandler to root logger
...
monitor(<configuration stuff>)
if __name__ == "__main__":
main()
所以我的问题是:我需要创建一个新的log
每个之后的对象os.fork()
?现有的全球格局会发生什么变化log
object?
按照我的方式做事,我是否可以解决我试图避免的问题(多个打开的文件/套接字)?这会失败吗?为什么会失败(我想知道未来类似的实现是否会失败)?
另外,“正常”(一log=
表达式)从多个进程记录到一个文件的方法失败?它会引发 IOError/OSError 吗?或者它只是没有将数据完全写入文件?
如果有人可以提供答案或链接来帮助我,那就太好了。谢谢。
FYI:
我正在 Mac OS X Lion 上进行测试,代码最终可能会在 Windows 计算机上的 CentOS 6 VM 上运行(如果这很重要的话)。无论我使用什么解决方案都不需要在 Windows 上工作,但应该在基于 Unix 的系统上工作。
UPDATE:这个问题已经开始不再记录特定行为,而更多地涉及 Linux 在分叉期间如何处理文件描述符的领域。我拿出一本大学教科书,似乎如果您从两个进程(而不是在分叉之前)以附加模式打开一个文件,只要您的写入不超过,它们都将能够正确写入该文件实际的内核缓冲区(尽管可能需要使用行缓冲,但仍不确定)。这将创建 2 个文件表条目和 1 个 v 节点表条目。打开文件然后分叉不应该起作用,但只要您不像以前那样超出内核缓冲区(我在之前的程序中已经这样做了),它似乎就可以工作。
所以我想,如果你想要独立于平台的多处理日志记录,你可以使用套接字并在每个分叉后创建一个新的 SocketHandler 以保证安全,正如 Vinay 下面建议的那样(这应该在任何地方都有效)。对我来说,由于我对运行软件的操作系统有很强的控制权,所以我想我会选择一个全局的log
带有 FileHandler 的对象(默认以附加模式打开,并且在大多数操作系统上进行行缓冲)。的文档open http://docs.python.org/library/functions.html#open说“负缓冲意味着使用系统默认值,通常对 tty 设备是行缓冲,对其他文件是完全缓冲。如果省略,则使用系统默认值。”或者我可以创建自己的日志流以确保行缓冲。需要明确的是,我同意:
# Process A
a_file.write("A\n")
a_file.write("A\n")
# Process B
a_file.write("B\n")
生产...
A\n
B\n
A\n
只要不产生...
AB\n
\n
A\n
Vinay(或其他任何人),我错了多少?让我知道。感谢您提供更多的清晰度/确定性。