Python子进程调用参数问题

3

我正在Linux下编写一个简单的Python脚本,使用subprocess在我的子网上对多个主机进行并发单次ping测试。

手动执行命令可以正常工作: ping -c 1 192.168.68.1

该脚本如下:

#!/usr/bin/python
from subprocess import call

path = "ping"
flags = "-c 1 "

for i in range(1,3):
    ip_addr = "192.168.68." + str(i)
    args = flags + ip_addr

    print "doing: {} {}".format(path, args)        
    call([path, args])

注释掉调用可以得到预期的输出结果:

doing: ping -c 1 192.168.68.1
doing: ping -c 1 192.168.68.2

使用call(),脚本似乎调用了ping命令,但是参数未知。输出如下:

doing: ping -c 1 192.168.68.1
Usage: ping [-aAbBdDfhLnOqrRUvV64] [-c count] [-i interval] [-I interface]
        [-m mark] [-M pmtudisc_option] [-l preload] [-p pattern] [-Q tos]
        [-s packetsize] [-S sndbuf] [-t ttl] [-T timestamp_option]
        [-w deadline] [-W timeout] [hop1 ...] destination
Usage: ping -6 [-aAbBdDfhLnOqrRUvV] [-c count] [-i interval] [-I interface]
         [-l preload] [-m mark] [-M pmtudisc_option]
         [-N nodeinfo_option] [-p pattern] [-Q tclass] [-s packetsize]
         [-S sndbuf] [-t ttl] [-T timestamp_option] [-w deadline]
         [-W timeout] destination
doing: ping -c 1 192.168.68.2
Usage: ping [-aAbBdDfhLnOqrRUvV64] [-c count] [-i interval] [-I interface]
        [-m mark] [-M pmtudisc_option] [-l preload] [-p pattern] [-Q tos]
        [-s packetsize] [-S sndbuf] [-t ttl] [-T timestamp_option]
        [-w deadline] [-W timeout] [hop1 ...] destination
Usage: ping -6 [-aAbBdDfhLnOqrRUvV] [-c count] [-i interval] [-I interface]
         [-l preload] [-m mark] [-M pmtudisc_option]
         [-N nodeinfo_option] [-p pattern] [-Q tclass] [-s packetsize]
         [-S sndbuf] [-t ttl] [-T timestamp_option] [-w deadline]
         [-W timeout] destination

似乎每次迭代都会调用ping两次,并且使用的args与我预期的不同。我注意到-6 参数是ping抱怨的。
我会非常感激任何帮助,特别是关于正确使用call()的方面。

更新:
添加了我正在尝试模拟的bash脚本:

#!/bin/bash
for ip in $(seq 1 2); do
    ping -c 1 192.168.68.$ip &
done

3
call([path, flags.strip(), ip_addr]) - undefined
2个回答

3
函数call的参数应该是一个列表中的单个元素,如下所示:
call(['ping','-c','1','192.168.68.2'])

我在我的环境中无法重现“双倍打印”的问题。

嗨Pablo,我尝试了一下 flags = ["-c", "1"] 然后在call()函数中尝试解包 call([path, *flags, ip_addr]) 但是出现了语法错误。难道在数组内部无法进行解包操作吗? - undefined
1
@user1330734:这是Python 3.5+的语法。 - undefined
@J.F. Sebastian 有趣的是,Python代码似乎是同步的,即每个ping调用似乎都在等待前一个完成。相比之下,我上面添加的分叉bash脚本需要大约5秒钟来完成IP范围1-254的操作。 - undefined
1
@user1330734 阅读关于subprocess.call(cmd)的文档。思考一下subprocess.Popen(cmd)subprocess.Popen(cmd).wait()之间的区别,以及哪一个更接近subprocess.call(cmd) - undefined
@J.F. Sebastian非常感谢您指引我找到正确的地方。为了实现并发性,我需要调用subprocess.Popen(cmd)。subprocess.call(cmd)似乎更接近于subprocess.Popen.wait()。Python脚本现在按预期执行,谢谢。 - undefined

0
如@Pablo所提到的,flagspath变量应该是列表元素,因此在调用call方法之前,将您的命令字符串转换为列表。
path = "ping"
flags = "-c 1"
cmd_list = [path] # convert string to list
cmd_list = cmd_list + flags.split(' ') # converting your flags string to list elements

call(cmd_list)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接