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

时间:2016-10-23 13:19:10

标签: python windows iterator pywin32

我尝试使用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

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

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

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

谢谢大家的帮助,对不起我的英语很糟糕...... :(

戴夫

1 个答案:

答案 0 :(得分:0)

问题是在函数handle返回后,对象file_descriptoropen可能会收集垃圾。 当您调用__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, ...)
    ...

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