【问题标题】:ValueError: Separator is not found, and chunk exceed the limitValueError:未找到分隔符,并且块超出限制
【发布时间】:2017-06-10 01:44:06
【问题描述】:

我正在通过 asyncio.subprocess 运行外部下载器脚本,每当我尝试下载大数据时,asyncio 都会出现以下错误:

asyncio.streams.LimitOverrunError: Separator is not found, and chunk 超出限制

这是什么原因,我该如何解决?

import asyncio, subprocess, websockets, json
from os.path import expanduser, sep

async def handler(websocket, path):
    print("New client connected.")
    await websocket.send('CONNECTED')
    path = expanduser("~") + sep
    try:
        while True:
            inbound = await websocket.recv()
            if inbound is None:
                break
            while inbound != None:
                cmd = ('downloader_script', '-v', '-p', '-o', '/home/blah/blah', inbound)
                process = await asyncio.create_subprocess_exec(*cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
                async for output in process.stdout:
                    for line in output.decode().split('\r'):
                        line = line.strip()
                        if line == '':
                            continue
                        data = {}
                        await asyncio.sleep(1)
                        if line.startswith('INFO:'):
                            data['INFO'] = line.split('INFO: ')[1]
                        elif line.startswith('['):
                            data['progress'] = line.split(']')[0][1:]
                        elif line.startswith('ERROR:'):
                            data['ERROR'] = line.split('ERROR: ')[1]
                        else:
                                data['message'] = line
                        print (data)
                        await websocket.send(json.dumps(data))
                await websocket.send(json.dumps({'progress': 'DONE'}))
                await websocket.send('bye!')
                break
    except websockets.exceptions.ConnectionClosed:
        print("Client disconnected.")

if __name__ == "__main__":
    server = websockets.serve(handler, '0.0.0.0', 8080)
    loop = asyncio.get_event_loop()
    loop.run_until_complete(server)
    loop.run_forever()

【问题讨论】:

  • await asyncio.sleep(1) 在使用async for 时不需要。我在下面更新了我的答案,举例说明如何使用tr\r 替换为\n
  • 据我了解,替换应该有效,但它没有。我想我的问题可能有点不清楚,对不起。我必须解析的输出中有一个进度条。奇怪的是,如果进度相对较短(比如 30 段),它运行良好,但如果我尝试下载更大的内容,我会在进度条处于 100% 甚至 exit(0) 时得到输出。
  • 但是,常规 subprocess 模块并非如此,两者之间的性能差异必须是微观的,因为对我而言使用常规子进程在我的输出中至少看起来是完全异步的。
  • 您的进度条进程在未发送到 tty 时可能正在缓冲其输出。

标签: python asynchronous async-await subprocess python-asyncio


【解决方案1】:

由于asyncio.subprocess 目前最适合使用换行符,也许可以尝试通过将\r 替换为\n 的东西来运行您的脚本。

这是一个可以提供帮助的小型 bash 脚本 (cr2lf.sh):

#!/bin/bash
$@ | tr '\r' '\n'

例子:

# slow_ugly_writer.py
import sys
import time

n = int(sys.argv[1])

for i in range(1, n + 1):
    time.sleep(0.5)
    print("*" * i, end="\r")

用法:

./cr2lf.sh python -u slow_ugly_writer.sh 10

在你的程序中:

cmd = ('crlf.sh', 'downloader_script', '-v', '-p', '-o', '/home/blah/blah', inbound) 

【讨论】:

    猜你喜欢
    • 2018-01-03
    • 1970-01-01
    • 1970-01-01
    • 2011-09-20
    • 2014-03-18
    • 1970-01-01
    • 2018-10-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多