Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork32k
Description
Bug report
Bug description:
This is not a bug per se as it diverges from the documentation, but Posix version ofsubprocess.Popen.communicate()
behaves less ideally when a large "memoryview"-able object with non-byte item is passed as theinput
argument. For example, suppose I have a simple pass-through process which takes a long input arrayx
of length greater than 512 and return it as is:
importsubprocessasspimportnumpyasnpx=np.random.randn(44100,dtype=float)# 8-byte data typeret=sp,run('pass_thru',input=x)y=np.frombuffer(ret.stdout,dtype=float)assertnp.array_equal(x,y)
This example fails the assertion only in Posix because the returned arrayy
shorter thanx
.
This appears to stem fromsp.Popen.communicate()
ifself._input:input_view=memoryview(self._input)#[snip]ifkey.fileobjisself.stdin:chunk=input_view[self._input_offset:self._input_offset+_PIPE_BUF]try:self._input_offset+=os.write(key.fd,chunk)exceptBrokenPipeError:selector.unregister(key.fileobj)key.fileobj.close()else:ifself._input_offset>=len(self._input):#[snip]
The indexedchunk
ofinput_view
sends more bytes ifself._input
is not a bytes-like whilelen(self._input)
counts the number of items. As suchself._input_offset
>len(self._input)
after the first few writes due to the mismatch in their units.
I think the if statement checks the bytes read againstinput_view.nbytes
instead oflen(self._input)
.
This use case is not officially supported as the input is expected to be bytes-like and not any arbitrary memoryview object, but it works under Windows, and this Posix codepath behavior is rather nasty as it works (as wrongly expected) for a short input (as is often the case for testing).
I believe an arbitrary memoryview object as a subprocess input works otherwise (based on my extensive uses passing audio and video data to and from FFmpeg) so perhaps I should label this issue as a feature request.
P.S., A fix for the example is to useret = sp,run('pass_thru', input=x.view('b'))
.
CPython versions tested on:
3.13
Operating systems tested on:
No response