我尝试使用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打开文件......所以......我错过了什么?
为什么使用迭代器协议我收到错误消息?这是线程相关的问题吗?我该如何解决?
我知道可能会有上千种解决方法,但我想了解为什么这段代码无效......
谢谢大家的帮助,对不起我的英语很糟糕...... :(
戴夫
答案 0 :(得分:0)
问题是在函数handle
返回后,对象file_descriptor
和open
可能会收集垃圾。
当您调用__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, ...)
...
仅存储其中一个可能就足够了,但我不确定是哪一个。存储两者是保存方式。