首页 > 解决方案 > 当python3链两个subprocess.run(如bash管道)得到错误“AttributeError:'bytes'对象没有属性'fileno'”

问题描述

bash 代码是:

mx=8;my=8;head -c "$((3*mx*my))" /dev/urandom | convert -depth 8 -size "${mx}x${my}" RGB:- /tmp/random.png

而python3中的代码:

#!/usr/bin/python3

import subprocess

result = subprocess.run(['head', '-c {}'.format(3 * size * size), '/dev/urandom'], stdout=subprocess.PIPE)
print('{}'.format(result))
result = subprocess.run(['convert', '-depth 8', '-size{}x{}'.format(size, size), 'RGB:-', '/tmp/random.png'], stdin=result.stdout, stdout=subprocess.PIPE)

但输出是:

$ python3 create_mosaic_images.py 
CompletedProcess(args=['head', '-c 192', '/dev/urandom'], returncode=0, stdout=b"j\xd1U0\x7f\xc0\x11\x9e\xcdJ\x88P\xdc\xe5\xd26\xee\xf3m\xe0\xf9S\xd5%0q\xfb\x01\xd4^\xbd^R\xe4\x9c\x9e\xb5\xaf\x99:B[\xdc4\x80\x1a\x8a>\xeb\x9e\xab\xae/\xa4\xf4\xc3u\xaca\x8efJ\x9fNK\xa2\xb0\x18\x98\x95\xb08\xeb\x07\xf6\x9d2Ko\x11\xa0\x98\xf7\x8b\x04'\xd4;\xe8\xa5SD\xc7\xf8\xe6;\x8b\x880\xb8\x1e~\xee>r\xf0\xc0g\xfb\xce\xd6\xfcq\x1a\x91\xa0t0\x96\xf47\x9cj\xd4\x9ac\x15z\x81\xf35\x8f\x1ay\xa2\x8av\xb5\xe4\x15ox\x00\x00O\xfa\x98\x17\xe1\x04\xd5\x8dx\xdf\x9a.\xce<b\xb2\x16\x15\x94\xbd\x17Z\x14\xba\xc5-?\xbcH\t\x9a~1y\xc5\xe6\xf5\xd2[\xfb\xc0k\x90\xdfB\xafje")
Traceback (most recent call last):
  File "create_mosaic_images.py", line 26, in <module>
    generate_random_pixels_square()
  File "create_mosaic_images.py", line 19, in generate_random_pixels_square
    result = subprocess.run(['convert', '-depth 8', '-size{}x{}'.format(size, size), 'RGB:-', '/tmp/random.png'], stdin=result.stdout, stdout=subprocess.PIPE)
  File "/usr/lib/python3.5/subprocess.py", line 693, in run
    with Popen(*popenargs, **kwargs) as process:
  File "/usr/lib/python3.5/subprocess.py", line 911, in __init__
    errread, errwrite) = self._get_handles(stdin, stdout, stderr)
  File "/usr/lib/python3.5/subprocess.py", line 1392, in _get_handles
    p2cread = stdin.fileno()
AttributeError: 'bytes' object has no attribute 'fileno'

好吧,我不知道什么是坏的。

标签: python-3.xsubprocesspipe

解决方案


你不能run像这样链接 2 个调用。

您需要第一次调用 use Popenresult.stdout真正的文件在哪里(result.stdout返回的run是一个bytes对象,而不是真正的文件,因为run返回时,该过程已经结束,所有输出都产生了,而不是Popen启动该过程并写入管道)

process1 = subprocess.Popen(['head', '-c','{}'.format(3 * size * size), '/dev/urandom'], stdout=subprocess.PIPE)
result = subprocess.Popen(['convert', '-depth','8', '-size{}x{}'.format(size, size), 'RGB:-', '/tmp/random.png'], stdin=process1.stdout, stdout=subprocess.PIPE)

另外,您的论点分裂是错误的。您不能包含空格,您必须执行完整拆分。

在这种情况下,更好的方法是关闭第一个进程,因为您已经可以在 python 中执行此操作:

with open('/dev/urandom','rb') as f:
    random_block = b"".join(f.readline() for _ in range(3 * size * size))
    result = subprocess.Popen(['convert', '-depth','8', '-size{}x{}'.format(size, size), 'RGB:-', '/tmp/random.png'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
    output,error = result.communicate(random_block);

推荐阅读