4

我正在尝试打开一个由另一个进程保持打开的日志文件并删除前几行。在 Unix 上,我只需做 a 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可以在这里帮助我还是我需要切换我的语言?

4

2 回答 2

3

即使应用程序将文件作为共享对象打开,Python 也不能,所以他们无法通过它的外观来相处。

也不是那么坏 :)。您可以(必须)使用CreateFileAugusto 指出的方法打开文件。您可以为此使用标准ctypes模块。在Using a struct as a function argument with the python ctypes 模块的问题中,您可以看到如何做到这一点。然后,您必须将 C 运行时文件描述符与您在上一步中获得的现有操作系统文件句柄相关联。您可以使用_open_osfhandleMS C 运行时库 (CRT) 执行此操作。您可以使用ctypes再次调用它;您可以将其作为ctypes.cdll.msvcrt._open_osfhandle. 然后,您必须将 Python 文件对象与您在上一步中获得的现有 C 运行时文件描述符相关联。要在 Python 3 中执行此操作,您只需将文件描述符作为第一个参数传递给内置open功能。根据文档

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

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

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

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

于 2013-08-15T21:43:40.817 回答
2

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

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

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

于 2013-08-13T15:11:31.960 回答