1

A standard feature Python's subprocess API is to combine STDERR and STDOUT by using the keyword argument

stderr = subprocess.STDOUT 

But currently I need the opposite: Redirect the STDOUT of a command to STDERR. Right now I am doing this manually using subprocess.getoutput or subprocess.check_output and printing the result, but is there a more concise option?

2
  • Just curious, why do you want to do the piping that way? To me it seems like the result would be exactly the same if you pipe STDERR to STDOUT like you mentioned. Commented Dec 13, 2022 at 9:41
  • 2
    @Tzane the results would be the same if this is being run in the terminal, but not if it's part of a pipeline or if it's being from something like cron. If you have a program that runs your script and ignores stdout but emails you if anything is written to stderr, you might want to redirect all the output to stderr, for instance. Commented Dec 13, 2022 at 9:51

1 Answer 1

2

Ouroborus mentions in the comments that we ought to be able to do something like

subprocess.run(args, stdout = subprocess.STDERR) 

However, the docs don't mention the existence of subprocess.STDERR, and at least on my installation (3.8.10) that doesn't actually exist.

According to the docs,

stdin, stdout and stderr specify the executed program’s standard input, standard output and standard error file handles, respectively. Valid values are PIPE, DEVNULL, an existing file descriptor (a positive integer), an existing file object with a valid file descriptor, and None.

Assuming you're on a UNIX-type system (and if you're not, I'm not sure what you're planning on doing with stdout / stderr anyway), the file descriptors for stdin/stdout/stderr are always the same:

  • 0 is stdin
  • 1 is stdout
  • 2 is stderr
  • 3+ are used for fds you create in your program

So we can do something like

subprocess.run(args, stdout = 2) 

to run a process and redirect its stdout to stderr.

Of course I would recommend you save that as a constant somewhere instead of just leaving a raw number 2 there. And if you're on Windows or something you may have to do a little research to see if things work exactly the same.

Update:

A subsequent search suggests that this numbering convention is part of POSIX, and that Windows explicitly obeys it.

Update:

@kdb points out in the comments that sys.stderr will typically satisfy the "an existing file object with a valid file descriptor" condition, making it an attractive alternative to using a raw fd here.

Sign up to request clarification or add additional context in comments.

4 Comments

On Windows subprocess.STDOUT = -2, so this is likely only UNIX specific like you said.
Yeah, I realized STDERR doesn't exist in subprocess after making my comment. There's also STD_ERROR_HANDLE, STD_INPUT_HANDLE, and STD_OUTPUT_HANDLE but I'm not sure if they work in this scenario.
@Tzane Looks like subprocess.STDOUT is -2 on Linux as well. I don't think that's an actual fd, it's just some value that subprocess chose that can't be an actual fd which it can use to ensure complete cross-platform support regardless of how weird the platform is.
Actually, you indirectly mention the solution, which turns out to be a face-palm worthy case of "I should have read the documentation better": Valid values are [...] an existing file object with a valid file descriptor, [...]. This means that the following usually works: subprocess.check_call(['ls', '-l'], stdout=sys.stderr). Though it could fail in cases, where a module overrides sys.stderr, so it is probably not as general as subprocess.STDOUT.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.