Как запустить функцию в фоновом режиме - PullRequest
0 голосов
/ 07 февраля 2019

Я анализирую последнюю строку постоянно обновляемого файла журнала.Если он совпадает, я хочу вернуть совпадение в список и запустить другую функцию, используя эти данные.Мне нужно следить за новыми записями и анализировать их, даже когда новая функция продолжается.

Я работаю над этим с разных точек зрения около недели с переменным успехом.Я попытался создать многопоточность, но столкнулся с проблемами при получении возвращаемого значения, я попытался использовать глобальную переменную, но не смог заставить ее работать.Я сейчас пытаюсь 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 голосов
/ 08 февраля 2019

с несколькими небольшими исправлениями вы почти запускаете это :) (комментарии внутри)

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 :)
0 голосов
/ 07 февраля 2019

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

Прелесть асинхронного решения в том, что вы можете легко запустить произвольное количество таких сопрограмм параллельно (например, вы можете запустить gather(main1(), main2()) во внешней сопрограмме и запустить), и пусть все они разделяют одну и ту же тему.

...