OSError: [Errno 22] Invalid argument in subprocess

后端 未结 3 1909
谎友^
谎友^ 2021-01-04 03:59

Python 3.3.3 Windows 7

Here is the full stack:
Traceback (most recent call last):
  File \"Blah\\MyScript.py\", line 578, in Call
    output = process.commun         


        
3条回答
  •  悲&欢浪女
    2021-01-04 04:53

    Previously communicate only ignored an EPIPE error when writing to the process stdin. Starting with 3.3.5, per issue 19612, it also ignores EINVAL (22) if the child has already exited (see Lib/subprocess.py line 1199).

    Background:

    process.communiciate calls process.stdin.write, which calls io.FileIO.write, which on Windows calls the C runtime _write, which calls Win32 WriteFile (which in this case calls NtWriteFile, which dispatches to the NamedPipe filesystem, as either an IRP_MJ_WRITE or FastIoWrite).

    If the latter fails, it sets a Windows system error code in the thread. In this case the underlying Windows error is probably ERROR_NO_DATA (232) because the child process has already exited. The C runtime maps this to an errno value of EINVAL (22). Then since _write failed, FileIO.write raises OSError based on the current value of errno.


    Addendum:

    There wouldn't have been a problem at all if the CRT instead mapped ERROR_NO_DATA to EPIPE. Python's own Windows error translation generally follows the CRT's, but per issue 13063, it makes an exception to map ERROR_NO_DATA to EPIPE (32). Thus if the child has already exited, _winapi.WriteFile raises BrokenPipeError.

    The following example replicates the EINVAL error given the child process has already exited. It also shows how _winapi.WriteFile (3.3.3 source link) would instead map this error to EPIPE. IMO, this should be considered a bug in Microsoft's CRT.

    >>> cmd = 'reg query hkcu'                                                
    >>> process = Popen(cmd, stdin=PIPE, stdout=PIPE, universal_newlines=True)
    >>> process.stdin.write(' ')
    Traceback (most recent call last):
      File "", line 1, in 
    OSError: [Errno 22] Invalid argument
    
    >>> hstdin = msvcrt.get_osfhandle(process.stdin.fileno())
    >>> _winapi.WriteFile(hstdin, b' ')                                       
    Traceback (most recent call last):
      File "", line 1, in 
    BrokenPipeError: [WinError 232] The pipe is being closed
    

提交回复
热议问题