【问题标题】:Passing arguments to shell script from Python从 Python 向 shell 脚本传递参数
【发布时间】:2016-03-20 15:28:36
【问题描述】:

我正在编写一个将参数传递给 shell 脚本的 python 程序。

这是我的python代码:

import subprocess

Process=subprocess.Popen('./copyImage.sh %s' %s str(myPic.jpg))

还有我的“copyImage.sh”:

#!/bin/sh

cp /home/pi/project/$1 /home/pi/project/newImage.jpg

我可以毫无问题地在终端上运行脚本。但是在执行python代码时,终端返回了"NameError: name 'myPic' is not defined"

如果我将语法更改为

Process=subprocess.Popen('./copyImage.sh %s' %s "myPic.jpg")

然后终端返回"OSError: [Errno 2] No such file or directory"

我已经关注了这个:Python: executing shell script with arguments(variable), but argument is not read in shell script,但它没有帮助。

【问题讨论】:

  • 您可以在python本身中复制文件。 shutil.copy2('/home/pi/project/myPic.jpg', '/home/pi/project/newImage.jpg')。无需复杂的子流程调用。

标签: python linux shell


【解决方案1】:

使用 os.system 调用方式如下:

  1. os.system 确实在环境中找到了您的 shell 脚本
  2. 您可以根据需要向目标 shell 脚本附加任意数量的参数

例子:

os.system('myshellscript1 ' + arg1 + ' ' + arg2)

【讨论】:

  • Python docs 说使用 subprocess 模块比使用这个函数更可取。
【解决方案2】:

虽然您有 2 个答案显示如何将 subprocess 与可迭代的参数一起使用,我建议您采用其中一种方式,但为了完整起见,如果您指定 shell=True,您可以使用包含完整命令的字符串,但是你要负责所有的引用和所有类似的参数。

Process=subprocess.Popen('./copyImage.sh %s' % shlex.quote("myPic.jpg"), shell=True)

请注意,除了添加 shell=True 之外,我还通过 shlex.quote 传递参数以让它处理任何特殊字符的转义,以使其在文件名来自用户输入时更安全,否则它可能包含 @987654328 @ 和另一个要运行的命令,例如。像myPic.jpg; rm -rf ~ 这样的输入会在执行时导致不好的事情发生。

如果您不指定shell=True,subrpocess 模块实际上会查找名为copyImage.sh myPic.jpg 的可执行文件,其中空格和两个单词都作为要运行的可执行文件的名称。

另外两个注意事项,对于 python 2 而不是 shlex.quote 使用 pipes.quote。此外,上面的 shell 脚本没有引用它的参数,因此不能使用带有空格或其他特殊字符的名称。应该修改它以引用其变量(即always a good idea):

#!/bin/sh

cp /home/pi/project/"$1" /home/pi/project/newImage.jpg

使用稍微不同的脚本:

#!/bin/bash
printf 'Arg 1 is: %s\n' "$1"

我们可以看到这项工作如下:

subprocess.check_call("./demoScript.sh %s" % shlex.quote("This has ; bad stuff"), shell=True)

stdout 上产生以下输出

Arg 1 is: This has ; bad stuff

【讨论】:

  • 既然要负责转义,能不能把这个加到例子里?
  • @thatotherguy 我确实在论点中引用了%s,但我会说得更多,哎呀,这仍然不够好(请参阅这种方法的问题)让我修复它以更正确地保护论点!
  • @thatotherguy 好的,现在应该好多了,谢谢提示!
  • 仍然对我不起作用,例如带空格的文件名。
  • @thatotherguy 如果您使用的是 op 脚本,还需要对其进行修改以处理带空格的名称
【解决方案3】:

subprocess 模块需要一个参数列表,而不是空格分隔的字符串。您尝试的方式导致 python 查找名为 "copyImage.sh myPic.jpg" 的程序并在没有参数的情况下调用它,而您想查找名为 copyImage.sh 的程序并使用一个参数调用它。

subprocess.check_call(['copyImage.sh', 'myPic.jpg'])

我还想提一下,由于您的脚本只是在 shell 中调用 copy,您可能应该去掉中间人,直接使用 python 的shutil.copy。它是比为此任务运行子进程更合适的工具。

【讨论】:

    【解决方案4】:

    安全可靠的方法是:

    subprocess.Popen(["./copyImage.sh", "myPic.jpg"])
    

    您的第一次尝试失败了,因为 Python 中的字符串文字需要引号。第二个失败是因为 Popen 默认不运行 shell(您链接的问题设置 Shell=true 来执行此操作,但它很脆弱而且很糟糕)。

    【讨论】:

      猜你喜欢
      • 2017-01-22
      • 1970-01-01
      • 1970-01-01
      • 2018-03-03
      • 1970-01-01
      • 1970-01-01
      • 2015-09-13
      • 2012-11-21
      • 1970-01-01
      相关资源
      最近更新 更多