无法使用 POpen 将参数传递给子进程

Unable to pass argument to subprocess with POpen

我目前正在研究为 ROS(机器人操作系统)创建通用配置工具。使用 subprocess.POpen()Tkinter 我正在创建这样的 treeview

由于 rospack list 的简洁方式,前两列的创建相当简单(该命令列出了系统上安装的所有包,包括开发人员创建的相应工作区内的包他自己的包)有效:

ros_packages_install_retrieve = subprocess.Popen(["rospack list"], shell=True, stdout=subprocess.PIPE)
ros_packages_installed = []
for ros_package in ros_packages_install_retrieve.stdout.readlines():
    ros_package_adapted = ros_package.split(" ")
    ros_package_adapted[1] = ros_package_adapted[1][:-1]
    ros_packages_installed.append(ros_package_adapted)

Requires 列是棘手的一列,因为调用 rospack depends <package> 时出现问题(列出(如果有的话)<package> 需要的所有包出现在系统上以构建 and/or 运行)。对于 ros_packages_installed 中的每个包,我调用以下函数:

def get_deps(ros_package):
    ros_package_deps_retrieve = subprocess.Popen(["rospack", "depends", ros_package], shell=True, stdout=subprocess.PIPE)
    ros_package_deps = []
    for ros_package_dep in ros_package_deps_retrieve.stdout.readlines():
        ros_package_dep = ros_package_dep.split("\n")
        ros_package_dep = ros_package_dep[:-1]
        ros_package_deps.append(ros_package_dep)

    return ros_package_deps

问题是我得到

[rospack] Error: no package given

和 return 值始终是一个空列表。我什至尝试将 ros_package 参数连接到命令本身,但都是徒劳的。

在我徒劳的尝试中,我发现了一些很奇怪的东西。 listdepends 实际上都是传递给 rospack 的参数。事实上,如果你只调用 rospack 你会得到一个错误提示你调用 rospack help 来查看可用的参数。

因此我尝试将这些东西分开并将 ["rospack", "list"]["rospack", "depends", "ros_package"] 传递给两个 POpen 调用。令我惊讶的是,我得到了

[rospack] Error: no command given. Try 'rospack help' [rospack]

[rospack] Error: no command given. Try 'rospack help'

这至少对我来说是一种相当奇怪的行为。

这是对如何 运行 Popen 的混淆。您应该使用 shell=True:

传递单个字符串
 ros_package_deps_retrieve = subprocess.Popen("rospack depends %s"rospack, shell=True, stdout=subprocess.PIPE)

或者将其作为一个完全独立的列表传递,并使用shell=False(默认,无需指定):

 ros_package_deps_retrieve = subprocess.Popen(["rospack", "depends", rospack], stdout=subprocess.PIPE)

请参阅此处的文档: https://docs.python.org/2/library/subprocess.html#popen-constructor

重要部分(以下是文档中的相关引述):

If shell is True, it is recommended to pass args as a string rather than as a sequence. ...

If args is a sequence, the first item specifies the command string, and any additional items will be treated as additional arguments to the shell itself.

所以当你传递 shell=True 并像 ['rospack', 'list'] 一样传递它时,rospack 最终成为命令,而 list 成为 [=35= 的参数]shell,不是你想要的。

shell=False 并且你像 ['rospack depends', rosmodule] 一样传递它时,这使得字符串 'rospack depends' 成为 运行 的命令,它不存在因此失败。