我正在使用subprocess在Python中调用bash命令,而且我得到的返回代码与shell显示的不同。
import subprocess
def check_code(cmd):
print "received command '%s'" % (cmd)
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p.wait()
print "p.returncode is '%d'" % (p.returncode)
exit()
if p.returncode == 0:
return True
else:
return False
#End if there was a return code at all
#End get_code()
当发送“ls / dev / dsk&> / dev / null”时,check_code返回0,但“echo $?”在终端产生“2”:
Welcome to Dana version 0.7
Now there is Dana AND ZOL
received command 'ls /dev/dsk &> /dev/null'
p.returncode is '0'
root@Ubuntu-14:~# ls /dev/dsk &> /dev/null
root@Ubuntu-14:~# echo $?
2
root@Ubuntu-14:~#
有谁知道这里发生了什么?
答案 0 :(得分:3)
根据subprocess.Popen
,您的Python脚本中使用的shell是sh
。这个shell是POSIX标准,而不是Bash,它有几个非标准的功能,如速记重定向&> /dev/null
。 {B} shell sh
将此符号解释为"在后台运行我,并将stdout重定向到/ dev / null"。
由于您的subprocess.Popen
在自己的背景中打开了sh
ls
,因此使用sh
的返回值代替ls
,这种情况是0。
如果你想用你的Python做Bash行为,我相信你可能不得不重新配置(可能重新编译)Python本身。使用sh
ls /dev/dsk 2> /dev/null
语法更简单。
答案 1 :(得分:0)
按照xi_的建议,我将命令分成空格描述的字段,但无法使用“&>”运行和“/ dev / null”。我把它们删除了,它起作用了。
然后我将命令全部重新组合在一起测试它而没有“&> / dev / null”,这也有效。似乎添加“&> / dev / null”会以某种方式关闭子进程。
Welcome to Dana version 0.7
Now there is Dana AND ZOL
received command 'cat /etc/fstab'
p.wait() is 0
p.returncode is '0'
received command 'cat /etc/fstabb'
p.wait() is 1
p.returncode is '1'
received command 'cat /etc/fstab &> /dev/null'
p.wait() is 0
p.returncode is '0'
received command 'cat /etc/fstabb &> /dev/null'
p.wait() is 0
p.returncode is '0'
root@Ubuntu-14:~# cat /etc/fstab &> /dev/null
root@Ubuntu-14:~# echo $?
0
root@Ubuntu-14:~# cat /etc/fstabb &> /dev/null
root@Ubuntu-14:~# echo $?
1
root@Ubuntu-14:~#
我最初在调用中添加了“&> / dev / null”,因为我在STDERR的屏幕上看到了输出。一旦我将stderr = PIPE添加到子进程调用中,就会消失。我只是试图默默地检查幕后输出的代码。
如果有人可以解释为什么在Python中的子进程调用中添加“&> / dev / null”会导致其意外行为,我很乐意选择它作为答案!
答案 2 :(得分:-1)
您将其用作subprocess.Popen(cmd, shell=True)
,cmd
为字符串。
这意味着子进程将使用参数在引擎/bin/sh
下调用。因此,您将获得shell
的退出代码。
如果您需要实际退出命令代码,请将其拆分为列表并使用shell=False
。
subprocess.Popen(['cmd', 'arg1'], shell=False)