Windows:使用 Win32API 迭代 python 中的文件

Windows: iterate on a file in python using Win32API

我正在尝试使用 Win32Api 读取 Python 中的文件,以便能够打开文件而无需在 Windows 系统上锁定它。

我已经能够打开文件甚至读取文件,但是当我尝试实现迭代器协议时,我收到一条我无法理解的错误消息。

这是重现问题的示例脚本

#!/usr/bin/env python

import os


class FileTail(object):
    def __init__(self, file):
        self.open(file)

    def open(self, file):
        """Open the file to tail and initialize our state."""
        fh = None

        import win32file
        import msvcrt

        handle = win32file.CreateFile(file,
                                      win32file.GENERIC_READ,
                                      win32file.FILE_SHARE_DELETE |
                                      win32file.FILE_SHARE_READ |
                                      win32file.FILE_SHARE_WRITE,
                                      None,
                                      win32file.OPEN_EXISTING,
                                      0,
                                      None)
        file_descriptor = msvcrt.open_osfhandle(
            handle, os.O_TEXT | os.O_RDONLY)

        fh = open(file_descriptor, encoding='utf-8',
                  errors='ignore', newline="\n")

        self.reopen_check = "time"

        self.fh = fh
        self.file = file

        # Uncommenting this code demonstrate that there's no problem reading the file!!!!
        # -------------------------------------------------------------------------------
        # line = None
        # self.wait_count = 0

        # while not line:
        #     line = self.fh.readline()

    def __iter__(self):
        return self

    def __next__(self):
        line = None
        self.wait_count = 0

        while not line:
            line = self.fh.readline()

        return line

# ##############################
# ENTRY POINT
# ##############################
if __name__ == "__main__":
    my_file = FileTail('C:\LOGS\DANNI.WEB\PROVA.LOG')

    for line in my_file:
        print(line)

现在,如果您尝试执行此脚本,您将收到此错误消息:

Traceback (most recent call last):
  File "C:\Users\me\Desktop\prova.py", line 63, in <module>
    for line in my_file:
  File "C:\Users\me\Desktop\prova.py", line 53, in __next__
    line = self.fh.readline()
OSError: [Errno 9] Bad file descriptor

如果我取消注释 "open" 方法中的注释代码,我可以读取整个文件,所以我认为问题不在于使用 win32 api 打开文件...所以...我错过了什么?

为什么使用迭代器协议时会收到错误消息?是线程相关的问题吗?我该如何解决?

我知道可能会有上千种解决方法,但我想了解为什么这段代码不起作用...

感谢大家的帮助,抱歉我的英语很糟糕...:(

戴夫

问题是对象 handlefile_descriptor 可能会在函数 open returns 之后被垃圾回收。 当您调用 __next__ 时,对象可能已被释放,从而引发 OSError: [Errno 9] Bad file descriptor。这也是当您在 open 函数本身中读取文件时它起作用的原因,因为对象仍然存在。

要解决这个问题,只需将对象存储为实例属性,这样至少有一个对它们的引用。

def open(...)
    ...
    self.handle = CreateFile(...)
    ...
    self.file_descriptor = msvcrt.open_osfhandle(self.handle, ...)
    ...
    self.fh = open(self.file_descriptor, ...)
    ...

可能只存储其中一个就足够了,但我不确定是哪一个。保存两者是保存方式。