stderr doesn't get captured when stdout=sys.stdout

73 Views Asked by At

I'm trying to run through subprocess.run() a command that will request user input via stdout, and in case the result is a failure, say why via stderr.

I want to capture stderr to show a friendlier error, but let stdout pass-through to the user's terminal. However, I only seem to be able to capture stderr if I'm also capturing stdout (either by explicitly passing stdout=sys.stdout or omitting it).

I'm no Python expert, and this whole subprocess/pipe/capture thing is getting messy for me. I'm trying to avoid going down Popen or looping output lines, if possible, as this seems to be an otherwise simple task. Could someone clarify what I'm doing wrong?

In the examples below, after the user inputs n, the script would error out.
I use #> to represent CLI output.

result = subprocess.run(cmd, text=True, stderr=subprocess.PIPE, stdout=sys.stdout)
print(result)
#> Question? [y/n] (user input starts) n <enter>
#> error: blah blah
#> CompletedProcess(args=[...], returncode=1, stderr='')


### the same happens if stdout is omitted,
### or if I try to check captured stderr from CalledProcessError instead
try:
    subprocess.run(cmd, text=True, check=True, stderr=subprocess.PIPE)
except subprocess.CalledProcessError as error:
    print(vars(error))
#> (user input starts) n <enter>
#> {'returncode': 1, 'cmd': [...], 'output': None, 'stderr': ''}


### However, if I also capture stdout, it works as expected...
### But then, the user cannot really interact, since the question
### is captured and never shown. The same happens if I try..except.
result = subprocess.run(cmd, text=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
print(result)
#> (user input starts) n <enter>
#> CompletedProcess(args=[...], returncode=1, stdout="Question? [y/n] ", stderr="\x07error: blah blah\n")

A reproducible gist can be found here... However, after some nudges from @Barmar, I created an example using a MariaDB image and the issue doesn't show up there as well - instead of everything going to stderr on the last code block, everything is going to stdout (which is bad but sort of expected).

I guess this could be closed as non-reproducible, unless someone get a great idea about my problem (which, again, isn't reproducible on the gist I wrote).

0

There are 0 best solutions below