如何 运行 'background' 中的函数
How to run a function in 'background'
我正在解析一个不断更新的日志文件的最后一行。如果匹配,我想 return 匹配到一个列表并使用该数据启动另一个函数。即使在新功能继续运行时,我也需要继续观察新条目并解析它们。
我从几个不同的角度进行了大约一周的工作,取得了不同程度的成功。我尝试线程化,但 运行 遇到获取 return 值的问题,我尝试使用全局变量但无法使其工作。我现在正在尝试 asyncio,但在让它工作时遇到更多问题。
def tail():
global match_list
f.seek(0, os.SEEK_END)
while True:
line = f.readline()
if not line:
time.sleep(0.1)
continue
yield line
def thread():
while True:
tail()
def somefun(list):
global match_list
#do things here
pass
def main():
match_list = []
f = open(r'file.txt')
thread=threading.Thread(target=thread, args=(f,))
thread.start()
while True:
if len(match_list) >= 1:
somefun(match_list)
if __name__ == '__main__':
main()
凭记忆写下以上内容..
我想要 tail() 到 return 到 somefun() 可以使用的列表的行。
我在让它工作时遇到问题,我将使用线程或 asyncio.. 此时可以使用任何东西 运行。
在 asyncio 中,您可能会使用两个协程,一个从文件中读取,另一个处理文件。由于他们使用队列进行通信,因此不需要全局变量。例如:
import os, asyncio
async def tail(f, queue):
f.seek(0, os.SEEK_END)
while True:
line = f.readline()
if not line:
await asyncio.sleep(0.1)
continue
await queue.put(line)
async def consume(queue):
lines = []
while True:
next_line = await queue.get()
lines.append(next_line)
# it is not clear if you want somefun to receive the next
# line or *all* lines, but it's easy to do either
somefun(next_line)
def somefun(line):
# do something with line
print(f'line: {line!r}')
async def main():
queue = asyncio.Queue()
with open('file.txt') as f:
await asyncio.gather(tail(f, queue), consume(queue))
if __name__ == '__main__':
asyncio.run(main())
# or, on Python older than 3.7:
#asyncio.get_event_loop().run_until_complete(main())
基于 asyncio 的解决方案的美妙之处在于,您可以轻松地并行启动任意数量的此类协程(例如,您可以在外部协程中启动 gather(main1(), main2())
,然后 运行 ) , 并让他们共享同一个线程。
通过一些小的修复你几乎运行这个:)(里面的评论)
match_list # should be at the module scope
def tail():
# f = open(...) ???
f.seek(0, os.SEEK_END)
while True:
line = f.readline()
if not line:
time.sleep(0.1)
continue
yield line
def thread():
for line in tail():
match_list.append(line) # append line
print("thread DONE!")
def somefun(list):
#do things here
while match_list:
line = match_list.pop(0)
print(line)
def main():
match_list = []
f = open(r'file.txt')
thread=threading.Thread(target=thread, args=(f,))
thread.start()
while True:
if match_list:
somefun(match_list)
time.sleep(0.1) # <-- don't burn the CPU :)
我正在解析一个不断更新的日志文件的最后一行。如果匹配,我想 return 匹配到一个列表并使用该数据启动另一个函数。即使在新功能继续运行时,我也需要继续观察新条目并解析它们。
我从几个不同的角度进行了大约一周的工作,取得了不同程度的成功。我尝试线程化,但 运行 遇到获取 return 值的问题,我尝试使用全局变量但无法使其工作。我现在正在尝试 asyncio,但在让它工作时遇到更多问题。
def tail():
global match_list
f.seek(0, os.SEEK_END)
while True:
line = f.readline()
if not line:
time.sleep(0.1)
continue
yield line
def thread():
while True:
tail()
def somefun(list):
global match_list
#do things here
pass
def main():
match_list = []
f = open(r'file.txt')
thread=threading.Thread(target=thread, args=(f,))
thread.start()
while True:
if len(match_list) >= 1:
somefun(match_list)
if __name__ == '__main__':
main()
凭记忆写下以上内容.. 我想要 tail() 到 return 到 somefun() 可以使用的列表的行。 我在让它工作时遇到问题,我将使用线程或 asyncio.. 此时可以使用任何东西 运行。
在 asyncio 中,您可能会使用两个协程,一个从文件中读取,另一个处理文件。由于他们使用队列进行通信,因此不需要全局变量。例如:
import os, asyncio
async def tail(f, queue):
f.seek(0, os.SEEK_END)
while True:
line = f.readline()
if not line:
await asyncio.sleep(0.1)
continue
await queue.put(line)
async def consume(queue):
lines = []
while True:
next_line = await queue.get()
lines.append(next_line)
# it is not clear if you want somefun to receive the next
# line or *all* lines, but it's easy to do either
somefun(next_line)
def somefun(line):
# do something with line
print(f'line: {line!r}')
async def main():
queue = asyncio.Queue()
with open('file.txt') as f:
await asyncio.gather(tail(f, queue), consume(queue))
if __name__ == '__main__':
asyncio.run(main())
# or, on Python older than 3.7:
#asyncio.get_event_loop().run_until_complete(main())
基于 asyncio 的解决方案的美妙之处在于,您可以轻松地并行启动任意数量的此类协程(例如,您可以在外部协程中启动 gather(main1(), main2())
,然后 运行 ) , 并让他们共享同一个线程。
通过一些小的修复你几乎运行这个:)(里面的评论)
match_list # should be at the module scope
def tail():
# f = open(...) ???
f.seek(0, os.SEEK_END)
while True:
line = f.readline()
if not line:
time.sleep(0.1)
continue
yield line
def thread():
for line in tail():
match_list.append(line) # append line
print("thread DONE!")
def somefun(list):
#do things here
while match_list:
line = match_list.pop(0)
print(line)
def main():
match_list = []
f = open(r'file.txt')
thread=threading.Thread(target=thread, args=(f,))
thread.start()
while True:
if match_list:
somefun(match_list)
time.sleep(0.1) # <-- don't burn the CPU :)