簡體   English   中英

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

如果我取消注釋“打開”方法中的注釋代碼,則可以讀取整個文件,因此我認為問題不在於使用win32 api打開文件...所以...我失蹤?

為什么使用迭代器協議會收到錯誤消息? 它是與線程相關的問題嗎? 我該如何解決?

我知道可能會有一千種解決方法,但我想了解為什么此代碼無法正常工作...

謝謝大家為您提供的幫助,對不起我的英語不好... :(

戴夫

問題在於,在函數open返回之后,對象handlefile_descriptor可能會被垃圾回收。 當您調用__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, ...)
    ...

僅存儲其中之一可能就足夠了,但是我不確定是哪一個。 保存兩者都是保存的方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM