如何 运行 '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 :)