Python 运行os.system/subprocess.call返回语法错误

Python 运行os.system/subprocess.call返回语法错误,python,bash,python-2.7,Python,Bash,Python 2.7,我想从Python2.7运行这个bash命令: time ( s=172.20.16 ; for i in $(seq 1 254) ; do ( ping -n -c 1 -w 1 $s.$i 1>/dev/null 2>&1 && printf "%-16s %s\n" $s.$i responded ) & done ; wait ; echo ) 我试着这样运行它: cmd = 'time ( s=172.20.16 ; for i in

我想从Python2.7运行这个bash命令:

time ( s=172.20.16 ; for i in $(seq 1 254) ; do ( ping -n -c 1 -w 1 $s.$i 1>/dev/null 2>&1 && printf "%-16s %s\n" $s.$i responded ) & done ; wait ; echo ) 
我试着这样运行它:

cmd = 'time ( s=172.20.16 ; for i in $(seq 1 254) ; do ( ping -n -c 1 -w 1 $s.$i 1>/dev/null 2>&1 && printf "%-16s %s\n" $s.$i responded ) & done ; wait ; echo )'

#1. subprocess.call(cmd.split())
#2. subprocess.call(cmd, shell=True)
#3. os.system(cmd)
但是所有返回的/bin/sh:1:Syntax error:word unexpected(expective)(expected“)”),在
bash
中运行时都运行良好。我还尝试将
/bin/bash
添加到命令头,但没有成功

使用
os.system('bash“{}”format(cmd))
时,它没有因为前面的错误而崩溃,但循环未正确展开(它打印了1..254,而不是将它们用作IP后缀)


通过将命令保存在bash脚本中,然后从python调用脚本,我成功地实现了这一点,但我更愿意直接这样做。这里的问题是什么?

您正在按空间分割以构造SupProcess调用方法的命令/参数数组;但请注意,有些参数包含空格,因此它应该算作一个参数,而不是两个(即:这一个:
“%-16s%s\n”

尝试根据此链接使用子流程


shell=True
使用
/bin/sh
<代码>/bin/sh不是
bash

保留shell脚本的所有问题,但使用bash调用它,如下所示:

cmd = 'time ( s=172.20.16 ; for i in $(seq 1 254) ; do ( ping -n -c 1 -w 1 $s.$i 1>/dev/null 2>&1 && printf "%-16s %s\n" $s.$i responded ) & done ; wait ; echo )'
subprocess.call(['bash', '-c', cmd])

将其重写为一个更好的shell脚本可能会变成:

cmd = r'''
time {
  s=172.20.16
  for ((i=1; i<=254; i++)); do
    { ping -n -c 1 -w 1 "$s.$i" >/dev/null 2>&1 && \
      printf "%-16s %s\n" "$s.$i" "responded"
    } &
  done
  wait
  echo
}
'''
subprocess.call(['bash', '-c', cmd])
cmd=r''
时间{
s=172.20.16
对于((i=1;i/dev/null 2>&1&&\
printf“%-16s%s\n“$s.$i”已响应
} &
完成
等待
回响
}
'''
子进程调用(['bash','-c',cmd])

请注意,我们使用的是
{…;}
,而不是
(…)
,用于分组(从而避免创建过多的子shell)“,我们总是引用替换。

您对
cmd
的赋值甚至不是有效的Python。
time
是bash内置的。它不能保证在其他shell中实现您所期望的功能,特别是在
/bin/sh
@CharlesDuffy中。在验证这是
时间之后,我还尝试使用/usr/bin/time与
which time
@CIsForCookies一起使用时,
/usr/bin/time
具有不同的语法。您不能像使用内置命令那样向它传递复合命令。(另一方面,您可以使用
['time','sh','c',cmd
,这样您就传递了一个简单的命令,
sh
)。而且,
哪个时间
在这种情况下是完全无用/毫无意义的;
哪个时间
甚至不知道shell函数、内置代码或别名是否存在。如果您想知道在bash中使用的是
时间
的哪个实现,您需要的是
键入时间
,而不是
哪个时间
拆分()无论您是否使用
子流程
都是一个问题。很高兴知道。是否需要详细说明?如果没有
shell=True
,则
子流程调用的
args
参数的预期格式是一个列表,每个argv值有一个条目。使用
string.split()
生成该列表适用于非常简单的情况,如
ls hello.txt
,但它会将
ls“hello World.txt”
更改为
['ls','hello','World.txt']
。对于需要shell连接它们的复合命令,即使使用shell语法感知的替换,如
shlex.split()
,并且确实需要重写以让shell进行拆分,或者用本机Python连接进程。这是有意义的。谢谢。没有解释所有情况,所以我不认为这是主要问题。Charles Duffy的答案解决了第二种情况。我正在使用您的答案,但现在我被另一件事困住了……输出分配给
x=子进程。检查\u输出(…)
'\n'
即使我得到了更多的输出行,但它们不知何故从
x中溜走了
这些行是真正的输出行,还是在stderr上?…如果要组合这两个流,请将
stderr=subprocess.STDOUT
作为单独的关键字参数添加到
subprocess.call()
。是的……我这样做只是为了检查您之前的评论。当然,我看到的输出实际上是stderr。谢谢!!
cmd = r'''
time {
  s=172.20.16
  for ((i=1; i<=254; i++)); do
    { ping -n -c 1 -w 1 "$s.$i" >/dev/null 2>&1 && \
      printf "%-16s %s\n" "$s.$i" "responded"
    } &
  done
  wait
  echo
}
'''
subprocess.call(['bash', '-c', cmd])