从Python向shell脚本传递参数

3
我是一名有用的助手,可以为您翻译文本。

我正在编写一个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'未定义"的错误。
如果我更改语法为
Process=subprocess.Popen('./copyImage.sh %s' %s "myPic.jpg")

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

我按照这个链接的方法尝试解决:Python:使用变量执行shell脚本,但在shell脚本中未读取参数,但没有帮助。


2
你可以在Python中复制文件。 shutil.copy2('/home/pi/project/myPic.jpg', '/home/pi/project/newImage.jpg')。不需要使用子进程调用使事情变得复杂。 - tdelaney
4个回答

3
subprocess模块需要传入一个参数列表,而不是空格分隔的字符串。你的方式导致Python去查找一个名为"copyImage.sh myPic.jpg"的程序并且不带任何参数调用它,然而你想要查找一个名为copyImage.sh的程序并且给它传递一个参数。请注意,保留原有HTML标签。
subprocess.check_call(['copyImage.sh', 'myPic.jpg'])

我还想提醒一下,由于你的脚本只是在shell中调用copy命令,所以你应该去掉中间人,直接使用Python的shutil.copy。这是比运行子进程更合适的工具。


3

使用os.system调用是正确的方法,因为:

  1. os.system可以在环境中找到您的shell脚本。
  2. 您可以将所需的参数附加到目标shell脚本上。

例如:

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

Python docs 表示使用 subprocess 模块比使用此函数更可取。 - wim

1
安全且健壮的方法是:


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

你的第一次尝试失败了,因为Python中的字符串字面量需要加引号。第二次尝试失败是因为Popen默认不运行shell(你链接的问题设置了Shell=true来实现这一点,但它很容易出错且不好)。

0

虽然您已经得到了两个答案,展示了如何使用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,subprocess模块实际上将寻找一个名为copyImage.sh myPic.jpg的可执行文件,其中空格和两个单词是要运行的可执行文件的名称。

还有两点需要注意的是,对于Python 2而言,可以使用pipes.quote代替shlex.quote。另外,上面的shell脚本没有对其参数进行引用,因此无法处理包含空格或其他特殊字符的名称。应该修改为引用它的变量(这是总是一个好主意):

#!/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)

它会在标准输出上产生以下输出

Arg 1 is: This has ; bad stuff

既然你需要负责转义,能否将其添加到示例中? - that other guy
@thatotherguy 我其实已经在参数中引用了“%s”,但我会更加明确地指出它,糟糕,这仍然不够好(请注意这种方法的问题),让我修复它以更恰当地保护参数! - Eric Renouf
@thatotherguy 好的,现在应该好了,感谢您的及时回复! - Eric Renouf
@thatotherguy 如果您正在使用op脚本,它也需要被修改以处理带有空格的名称。 - Eric Renouf
如果您正在使用 shlex.quote(),请不要同时添加文字双引号;调用的输出假定为未被引用的初始上下文。 - Charles Duffy
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接