The correct subprocess spell with shell = True to get the result and not hang

Inside the subprocess call, I want to use shell = True so that it searches the tracks (the code below), however it has an annoying side effect of creating a subprocess spawn a child process (which then needs to be "talk" () d / poll () ed / wait ( ) ed / terminate () d / kill () ed / whatevah).

(Yes, I know that globbing can also be done using fnmatch / glob , but please show me the β€œcorrect” use of this subprocess, that is, the minimum spell to get stdout and stop the child process.)

This works fine (returns the result):

subprocess.check_output(['/usr/bin/wc','-l','[AZ]*/[AZ]*.F*'], shell=False)

but it freezes

subprocess.check_output(['/usr/bin/wc','-l','[AZ]*/[AZ]*.F*'], shell=True)

(PS: This seriously complicates the fact that you cannot specify a subprocess that you need some , but not all , for example, globbing functions, but not spawn. I think there is a decent PEP in this case if someone wants to comment , i.e. pass to the tuple Boolean or an or from binary flags)

(PPS: idiom about whether you go through subprocess...(cmdstring.split() or [...]) , just a trivial idiomatic difference. I say tomato, you say that I think. Motivation - this command is fixed , but I can name it more than once with a difference of specifications.)

+4
source share
1 answer

Firstly, there is very little space for passing an array:

 subprocess.check_output(['/usr/bin/wc','-l','AZ*/AZ*.F*'], shell=True) 

... since it just starts wc with no arguments, the arguments -l and AZ*/AZ*.F* are also passed in the shell as arguments (for the shell, not for wc ). Instead, you want:

 subprocess.check_output('/usr/bin/wc -l AZ*/AZ*.F*', shell=True) 

Before fixing, it freezes because wc has no arguments and reads from stdin. I would suggest that stdin be passed in private, and not passed through your Python program stdin (as by default).

An easy way to do this, since you have shell=True :

 subprocess.check_output( '/usr/bin/wc -l AZ*/AZ*.F* </dev/null', shell=True) 

... alternately:

 p = subprocess.Popen('/usr/bin/wc -l AZ*/AZ*.F*', shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=None) (output, _) = p.communicate(input='') 

... which will provide an empty stdin from Python code, rather than relying on the shell.

+6
source

Source: https://habr.com/ru/post/1403555/


All Articles