【问题标题】:shell command fails with subprocess.call() in Pythonshell 命令在 Python 中使用 subprocess.call() 失败
【发布时间】:2013-11-14 00:25:40
【问题描述】:

我无法使用 subprocess.call() 从 python 脚本运行 shell 命令。如果我复制 python 输出并粘贴到 shell 中,但当我通过 subprocess.call() 调用命令时,下面的测试有效。任何人都可以阐明我的错误/想法吗?我刚从编程开始,认为这是“只见树木不见森林”的事情,还有其他关于此的帖子,但我无法将它们应用于我的问题。

我认为 shell 脚本没有得到它的参数。我已经设置了shell=True 并尝试了 ' 和 " 围绕带有空格的 args。

import subprocess as s

fromCall = 'MB7UZ-1'
toCall = 'APRS'
path = 'via WIDE1-1'
ax25Port = 'aprs'
command = "/sbin/beacon"
packet = ":Test Beacon 4"

command_args = "-c '{0}' -d '{1} {2}' -s {3} '{4}'".format(fromCall, toCall, path, ax25Port, packet)

s.call([command, command_args], shell=True)
print repr(command_args)

将以下内容打印到控制台

/sbin/beacon -c MB7UZ-1 -d 'APRS via WIDE1-1' -s aprs ':Test Beacon 4'

如果我复制整行并粘贴回 shell,/sbin/beacon 程序将按预期工作。

我在这里和谷歌进行了广泛的搜索,一些帖子建议将参数转换为 UTF-8 ...

Python 2.7.3 (default, Feb 27 2013, 13:38:49)
[GCC 4.7.2 20120921 (Red Hat 4.7.2-2)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import locale ; locale.getdefaultlocale()
('en_US', 'UTF-8')

...鉴于上面的输出,我认为这不是问题,但不知何故我还是发现自己提到了它!

【问题讨论】:

    标签: python python-2.7 subprocess


    【解决方案1】:

    s.call 的参数应该是这样的:[command, "arg1", "arg2", "arg3", ...],你传递了[command, "arg1 arg2 arg3"] 所以/sbin/beacon 只得到一个参数:

    -c MB7UZ-1 -d 'APRS via WIDE1-1' -s aprs ':Test Beacon 4'
    

    你有两个选择,更好的一个是将论点分开。比如:

    import subprocess as s
    
    fromCall = 'MB7UZ-1'
    toCall = 'APRS'
    path = 'via WIDE1-1'
    ax25Port = 'aprs'
    command = "/sbin/beacon"
    packet = ":Test Beacon 4"
    
    command = ["/sbin/beacon", "-c", fromCall, "-d", " ".join((toCall, path)), "-s",
               ax25Port, packet]
    s.call(command)
    

    或者我不喜欢的选项,将单个字符串传递给s.call,然后让外壳为您拆分参数。只有使用 shell=True 才能执行此操作。

    import subprocess as s
    
    fromCall = 'MB7UZ-1'
    toCall = 'APRS'
    path = 'via WIDE1-1'
    ax25Port = 'aprs'
    command = "/sbin/beacon"
    packet = ":Test Beacon 4"
    
    command = command + " -c '{0}' -d '{1} {2}' -s {3} '{4}'".format(fromCall, toCall, path, ax25Port, packet)
    
    s.call(command, shell=True)
    print repr(command)
    

    【讨论】:

    • 其实更糟。获取参数的是外壳程序(shell=True 等效于 ['/bin/sh', '-c'] + [command, "arg1 arg2 arg3"] 此处)。在第二个代码示例中使用 pipes.quote
    • @J.F.Sebastian,我对pipes.quote 不太熟悉。如果您想添加它,请随时编辑我的答案。
    • 我只会删除 shell=True 变体。
    • 谢谢 Bi Rico,我想我误读了手册,没有意识到您将参数添加为列表。 J.f.Sebastian,感谢您的评论 - 手册上说 pipes.quote 自 2.7 起已贬值,改为使用 shlex。您的评论给了我另一个线索来跟进,谢谢!
    • @BiRico 我使用了您的第一个示例,效果很好。现在我理解了我将尝试使用Popen 实现的论点。这现在是有道理的,谢谢! ;-)
    猜你喜欢
    • 2020-03-29
    • 1970-01-01
    • 2010-09-25
    • 2023-03-24
    • 1970-01-01
    • 2014-07-06
    • 1970-01-01
    • 2016-10-09
    • 1970-01-01
    相关资源
    最近更新 更多