user5500127
user5500127

Reputation:

Python subprocess.check_output() seems to ignore arguments

First of all, I read as many related questions to subprocess.check_output() as I could find, but still struggle to identify the problem.

If I execute kill -l 1 in the shell, I get the corresponding signal name for 1, which is HUP. I need the same behaviour in my python script, so I use:

>>> subprocess.check_output(['kill', '-l', '1'])
b'HUP INT QUIT ILL TRAP ABRT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT\nCHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH POLL PWR SYS\n'

The subprocess seems to ignore the '1' in the argument list and instead executes kill -l.

I tried different versions, the argument as a list or string, with shell optione True and False, but none seem to work.

Any ideas what could be the reason? Using python3.4 on a Ubuntu14.04.

Thanks!

Upvotes: 1

Views: 465

Answers (1)

ShadowRanger
ShadowRanger

Reputation: 155418

Possible cause: The kill command in your shell is executing a shell built-in (most shells have one, because you need to be able to kill without a process launch when you have runaway fork bombs and the like), whereas check_output (not executing within a shell by default) is running the kill executable found in your PATH (often /bin/kill, but not always, running type -P kill in bash will tell you where that executable is).

Odds are, the built-in supports the switches you're looking for, the executable does not. In bash, try running type -P kill, then explicitly running the /full/path/to/kill -l 1 to see if the kill check_output is finding actually supports that invocation. Often there are subtle differences between different implementations of kill.

The best solution to this is probably to avoid expensive and pointless subprocess launches and check the Python definitions for the signals. For example, in Python 3.5, it's trivial to construct a mapping from the signals known by Python to their Python names:

import signal

sigdict = {sig.value: sig.name for sig in signal.Signals}

print(sigdict[1])
CTRL_BREAK_EVENT  # <-- The output on my Windows box. On your machine, it would probably be SIGHUP

In older Python where the names aren't enums, you can use similar code using dir of the module, filtering for names whose __module__ is signal and whose values are integers to construct the mapping.

Upvotes: 2

Related Questions