使用协程将stdin读取为二进制

时间:2018-07-17 11:27:49

标签: python-3.x python-asyncio

如果我们有文件的路径,我已经使用aiofiles来读取文件

#! /usr/bin/python3.6
import asyncio
import aiofiles

async def read_input():
    async with aiofiles.open('hello.txt', mode='rb') as f:
        while True:
            inp = await f.read(4)
            if not inp: break
            print('got :' , inp)

async def main():
    await asyncio.wait([read_input()])

event_loop = asyncio.get_event_loop()
event_loop.run_until_complete(main())
event_loop.run_forever()

我需要从标准输入中以./reader.py < file.txt读取文件 上面的代码以二进制形式读取文件。 但是我需要使用协程将stdin读取为二进制。我不知道有什么办法。

1 个答案:

答案 0 :(得分:1)

我正在为自己的问题发布可能的解决方案。

第一个解决方案是@ user4815162342所建议的:

async def read_input():
    async with aiofiles.open('/dev/stdin', mode='rb') as f:
        while True:
            inp = await f.read(4)
            if not inp: break
            print('got :' , inp)

它是特定于平台的,在Windows上不起作用。

此问题的另一种可能的解决方法是使用aioconsole的功能:

async def read_input():
    stdin, _ = await aioconsole.get_standard_streams()
    while True:
        line = await stdin.read(4)
        if not line: break
        print('got',line)

这似乎更健壮且与平台无关。这也有一个小问题,它不能读取./check.py < hello.bz2之类的压缩文件,但对于普通文件也可以正常工作。另一方面,aiofile方法可与./check.py < hello.bz2配合使用。

注意:在./check.py < hello.bz2上使用aioconsole方法执行时,我们会收到此错误

Task exception was never retrieved
future: <Task finished coro=<read_aioconsole() done, defined at ./input.py:21> exception=UnicodeDecodeError('utf-8', b'BZh91AY&SY\x89\x9a\xef"\x00\x00\x05\xc8\x00\x00\x10\x1f\x80 \x001\x0c\x00\xd0\xf4\'\r\xd0\xb5%\xe2\xeeH\xa7\n\x12\x113]\xe4@', 10, 11, 'invalid start byte')>
Traceback (most recent call last):
  File "./input.py", line 24, in read_aioconsole
    line = await stdin.read(4)
  File "/usr/local/lib/python3.6/dist-packages/aioconsole/stream.py", line 82, in read
    data = yield from self.loop.run_in_executor(None, self.stream.read, n)
  File "/usr/lib/python3.6/concurrent/futures/thread.py", line 56, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/lib/python3.6/codecs.py", line 321, in decode
    (result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x89 in position 10: invalid start byte