我正在编写一个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但它没有帮助。
答案 0 :(得分:4)
使用os.system调用是这样的方式:
示例:
os.system('myshellscript1 ' + arg1 + ' ' + arg2)
答案 1 :(得分:2)
subprocess
模块需要一个参数列表,而不是一个以空格分隔的字符串。你尝试的方式导致python寻找一个名为"copyImage.sh myPic.jpg"
的程序并且不带参数调用它,而你想要查找一个名为copyImage.sh
的程序并用一个参数调用它。
subprocess.check_call(['copyImage.sh', 'myPic.jpg'])
我还想提一下,因为你的脚本只是在shell中调用copy,你应该切断中间人并直接使用python的shutil.copy
。它比为此任务运行子进程更合适。
答案 2 :(得分:1)
安全可靠的方式是:
subprocess.Popen(["./copyImage.sh", "myPic.jpg"])
您的第一次尝试失败,因为字符串文字在Python中需要引号。第二个失败是因为Popen默认情况下没有运行shell(你链接的问题设置Shell=true
来执行此操作,但它很脆弱且不好)。
答案 3 :(得分:-1)
虽然你有两个答案显示如何使用subprocess
和参数的迭代,我建议你选择其中一种方法,为了完整性你可以使用包含完整命令的字符串,如果你指定{{ 1}},但是你负责所有的引用和所有类似的参数。
shell=True
请注意,除了添加Process=subprocess.Popen('./copyImage.sh %s' % shlex.quote("myPic.jpg"), shell=True)
之外,我通过shlex.quote
传递参数,让它处理转义任何特殊字符,以便在文件名来自用户输入时使其更安全一些,否则它可以例如,包括shell=True
和另一个要运行的命令。像;
这样的输入会在执行时导致坏事发生。
如果您没有指定myPic.jpg; rm -rf ~
,则subrpocess模块实际上将查找名为shell=True
的可执行文件,其中包含空格和两个单词作为要运行的可执行文件的名称。
另外两个注释,对于python 2而不是copyImage.sh myPic.jpg
使用shlex.quote
。此外,上面的shell脚本不引用其参数,因此不能使用带空格或其他特殊字符的名称。应修改它以引用其变量(always a good idea):
pipes.quote
脚本略有不同:
#!/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