【问题标题】:On Windows, how to open for writing a file already opened for writing by another process?在 Windows 上,如何打开以写入已被另一个进程打开以写入的文件?
【发布时间】:2013-08-15 02:54:30
【问题描述】:

我正在尝试打开一个由另一个进程保持打开的日志文件并删除前几行。 在 Unix 上,我只需执行 os.open('/tmp/file.log', os.O_NONBLOCK),这将使我更接近我的目标。

现在我被 Windows 卡住了,我需要以某种方式轮换此日志,而无需结束保存该文件的应用程序。这甚至可能吗?

起初我考虑在应用程序期望日志所在的位置打开一个文件句柄,并在 Python 中充当文件句柄的管道,但我在 Windows 上也找不到任何方法。

我也想过只是定期移动文件并让应用程序重新创建文件,但由于它正被另一个进程使用,这并没有多大好处。

也想到了O_SHLOCK,但话又说回来,那是 Unix 而不是 Windows。 所以我去找了 mmap 文件,希望它能让它更灵活一点,但这让我无处可去。

import mmap
import contextlib
import time

with open(r'test.log', 'r+') as f:
    with contextlib.closing(mmap.mmap(f.fileno(), 0)) as m:
        while 1:
            line = m.readline()
            if len(line) > 0:
                print line
            time.sleep(0.5)

这会导致应用程序无法访问该文件,因为 Python 正在持有它(反之亦然)。

想到了signal.SIGHUP,但这在 Windows 中也不存在,所以回到第一个问题。

我卡住了,我已经尝试了所有方法,Python 可以在这里帮助我还是我需要切换我的语言?

【问题讨论】:

  • 它是哪个 Python - 2 还是 3?
  • 2.6.很抱歉没有早点澄清。
  • 请注意O_NONBLOCK标志与多个进程同时打开同一个文件无关。

标签: python windows logging file-io logrotate


【解决方案1】:

即使应用程序将文件作为共享对象打开,Python 也不能 所以他们不能从外表上相处。

还不错:)。正如 Augusto 所指出的,您可以(必须)使用 CreateFile 打开文件。您可以为此使用标准的 ctypes 模块。在问题Using a struct as a function argument with the python ctypes module 中,您可以了解如何操作。然后,您必须将 C 运行时文件描述符与您在上一步中获得的现有操作系统文件句柄相关联。您可以使用 MS C 运行时库 (CRT) 中的 _open_osfhandle 来执行此操作。您可以使用 ctypes 再次调用它;您可以使用ctypes.cdll.msvcrt._open_osfhandle 访问它。然后,您必须将 Python 文件对象与您在上一步中获得的现有 C 运行时文件描述符相关联。要在 Python 3 中执行此操作,您只需将文件描述符作为第一个参数传递给内置 open 函数。根据文档

file 是一个字符串或字节对象,给出文件的路径名(绝对或相对于当前工作目录) 被打开或要包装的文件的整数文件描述符

在 Python 2 中你必须使用 os.fdopen;根据文档,它的任务是

返回一个连接到文件描述符fd的打开文件对象

不应该要求以上所有内容来做这么简单的事情。当 CPython 在 Windows 上的实现开始使用本地 Windows API 处理文件而不是通过不能访问 Windows 平台的许多功能的 C 运行时库时,希望它会简单得多。有关详细信息,请参阅Add new io.FileIO using the native Windows API 问题。

【讨论】:

  • 完美,我实际上制作了一个更丑陋的版本,我将应用程序包装在一个子进程中,然后输出标准输出并将其发送到我的 syslog-ng 服务器。但我会尽快用这个替换我丑陋的黑客!干杯伙伴,正是我需要的!
【解决方案2】:

您对生成日志文件的应用程序有任何控制权吗?因为根据该应用程序打开文件的方式,您确实无法修改它。

这个链接在这里可能看起来离题,但在 Windows 深处,决定文件访问其他应用程序的是CreateFile 函数的dwShareMode 参数:http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858%28v=vs.85%29.aspx

应用程序应该启用FILE_SHARE_WRITE 和可能的FILE_SHARE_DELETE,而且它应该在每次写入文件时刷新和更新文件位置。看了open()的Pythondocumentation,没有这么详细的参数。

【讨论】:

  • 首先,谢谢!其次,我提到了os.open(),它本身就是一种更手动的方式来处理open(),并且还提到它在Windows 中缺少SHARE 选项(这是一个错误)。即使应用程序将文件作为共享对象打开,Python 也不能,因此他们无法通过它的外观来相处。此外,除了在打开日志文件时启用共享标志之外,我无法修改原始应用程序(C 代码)。
  • How to create a temporary file that can be read by a subprocess?。有一个指向tempfile.NamedTemporaryFile not particularly useful on Windows Python 错误的链接,其中有关于在 Windows 中由多个进程打开同一个文件的有趣讨论。
猜你喜欢
  • 1970-01-01
  • 2015-02-19
  • 1970-01-01
  • 2019-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多