从Python传递参数到shell脚本

问题描述 投票:1回答:4

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

这是我的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 linux shell
4个回答
2
投票

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

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

我还想提一下,因为你的脚本只是在shell中调用copy,你应该切掉中间人并直接使用python的shutil.copy。它比为此任务运行子进程更合适。


4
投票

使用os.system调用是这样的:

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

例:

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

1
投票

安全可靠的方式是:

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

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


-1
投票

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

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

请注意,除了添加shell=True之外,我通过shlex.quote传递参数,让它处理转义任何特殊字符,以使文件来自用户输入时更安全一些,否则它可能包含;和另一个要运行的命令,例如。像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
© www.soinside.com 2019 - 2024. All rights reserved.