如何在“后台”运行功能

时间:2019-02-07 18:55:38

标签: python-3.x python-asyncio python-multithreading

我正在解析持续更新的日志文件的最后一行。如果匹配,我想将匹配返回到列表并使用该数据启动另一个功能。即使新功能继续运行,我也需要继续监视新条目并解析它们。

我已经从几个不同的角度研究了大约一个星期,并取得了不同的成功。我尝试使用线程,但是遇到获取返回值的问题,我尝试使用全局变量,但无法使其正常工作。我现在正在尝试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()将行返回到somefun()可以使用的列表。 我在使它无法正常工作时遇到问题,我将使用线程或asyncio ..使其在此刻运行。

2 个答案:

答案 0 :(得分:0)

在异步中,您可能会使用两个协程,一个协程从文件读取,另一个协程处理文件。由于它们使用队列进行通信,因此不需要全局变量。例如:

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())

基于异步的解决方案的优点在于,您可以轻松地并行启动任意数量的此类协程(例如,您可以在外部协程中启动gather(main1(), main2())并运行它们),并将它们共享相同的线程。

答案 1 :(得分:-1)

通过一些小修复,您几乎可以运行此:)(内部评论)

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 :)