Как избежать «ValueError: Разделитель не найден, а порция превышает предел» - PullRequest
2 голосов
/ 01 апреля 2019

У меня есть сервер, который использует asyncio следующим образом:

proc = await asyncio.subprocess.create_subprocess_exec(
    command,
    stdout=asyncio.subprocess.PIPE, 
    stderr=asyncio.subprocess.STDOUT)

async for line in proc.stdout:
    line = line.decode('utf-8').strip()
    print(line)

Проблема в том, что если proc.stdout содержит слишком длинную строку, в строке "for" появляется сообщение об ошибке:

ValueError: Separator is not found, and chunk exceed the limit

Как я могу обнаружить такие длинные строки, чтобы заранее избежать этой ошибки?

1 Ответ

1 голос
/ 01 апреля 2019

Как документация говорит:

Аргумент limit устанавливает ограничение буфера для StreamReader оболочек для Process.stdout и Process.stderr (если subprocess.PIPE передано Аргументы stdout и stderr).

Кажется, это то, что нам нужно.

Предел по умолчанию кажется 64 КиБ, вы можете попробовать что-нибудь выше:

proc = await asyncio.subprocess.create_subprocess_exec(
    command,
    limit = 1024 * 128,  # 128 KiB
    stdout=asyncio.subprocess.PIPE, 
    stderr=asyncio.subprocess.STDOUT)

Upd:

Я просто хочу обрезать / игнорировать слишком длинные строки. Это возможно?

Вы можете подавить ошибки на длинных линиях и продолжить после этого. Следующий код (протестирован на Windows) показывает идею:

import asyncio


async def main():
    proc = await asyncio.subprocess.create_subprocess_exec(
        *[
            'wget', 
            '--help'
        ],
        limit = 20,
        stdout=asyncio.subprocess.PIPE, 
        stderr=asyncio.subprocess.STDOUT)

    while True:
        try:
            async for line in proc.stdout:
                line = line.decode('utf-8').strip()
                print(line)
        except ValueError:
            continue
        else:
            break


loop = asyncio.ProactorEventLoop()
asyncio.set_event_loop(loop)
loop.run_until_complete(main())
...