[英]How to create a non-blocking generator to read a file?
我正在尝试创建一个文件生成器,它允许我继续逐行读取文件(CSV),并在新行添加到文件时继续运行(如连续日志),但也保持等待/运行在日志中找不到新行时的背景。
我试过使用aiofiles ,但我不知道如何从我的同步功能/主 function 运行异步 function。 然后我尝试了trio ,并使用以下代码可以读取文件中的行。
async def open_file(filepath):
with open(filepath, newline='') as f:
first_line = True
_reader = csv.reader(f, lineterminator='\n')
for row in _reader:
if row:
# skip header row
if first_line:
first_line = False
else:
print(tuple(row)) # yield tuple(row) here gives the error stated below
else:
await trio.sleep(1)
trio.run(open_file, 'products.csv')
但是脚本在读取行后停止,并且不会在后台等待更多行。 当我将print(row)
替换为yield tuple(row)
(实际上将返回一个生成器)时,我收到错误TypeError: start_soon expected an async function but got an async generator <async_generator object open_file at 0x1050944d0>
。
所以print
行工作正常,但yield
不是
我怎样才能解决这个问题? 另外,这将有助于并行读取行吗?
更新:
请不要说我必须使用csv.reader
来读取行,因为某些行包含\n
,这是正确读取记录的唯一方法。
迭代器对您的情况没有帮助,因为迭代器在到达文件末尾时立即停止
您可能会在以下模块中查找类似的功能 - https://github.com/kasun/python-tail/blob/master/tail.py
def follow(filename):
with open(filename) as file_:
file_.seek(0,2) # Remove it if you need to scan file from the beginning
while True:
curr_position = file_.tell()
line = file_.readline()
if not line:
file_.seek(curr_position)
yield None
else:
yield line
然后,您可以创建一个生成器,如果行尚未准备好,则生成 None ;如果文件中有下一行可用,则生成字符串。 使用next()
function 您可以以非阻塞方式逐行获取。
以下是你如何使用它:
non_blocking_reader = follow("my_file.txt")
# do something
line = next(non_blocking_reader)
if line is not None: # You need to distinguish None from empty string, so use `is not` not just `if line:`
# do something else
# do something else
next_line = next(non_blocking_reader)
# ...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.