我正在尝试创建一个在Mac终端上运行perl脚本的python脚本。流行的3D打印机切片引擎Slic3r能够使用命令行使用,这是用Perl编写的。我想写一个python脚本来自动化一些进程,这是我最熟悉的语言。如果我输入我想直接使用的命令到终端,它可以正常工作,但是,如果我尝试使用python的subprocess
,它适用于某些命令但不适用于其他命令。
例如,如果我使用我的脚本使用docs中概述的语法来获取Slic3r版本,则它可以正常工作。这个脚本有效:
import os
import subprocess
os.system("cd Slic3r")
perl = "perl"
perl_script = "/Users/path/to/Slic3r/slic3r.pl"
params = "--version"
pl_script = subprocess.Popen([perl, perl_script, params], stdout=sys.stdout)
pl_script.communicate()
print 'done'
返回:
1.3.0-dev
done
如果我使用一个命令,如--info(请参阅修复模型下的Slic3r文档以获取更多信息),请使用相同的脚本:
在:
import os
import subprocess
os.system("cd Slic3r")
perl = "perl"
perl_script = "/Users/path/to/Slic3r/slic3r.pl"
params = "--info /Users/path/to/Desktop/STL_Files/GEAR.stl"
pl_script = subprocess.Popen([perl, perl_script, params], stdout=sys.stdout)
pl_script.communicate()
print 'done'
输出:
Unknown option: info /Users/path/to/Desktop/STL_Files/GEAR.stl
Slic3r 1.3.0-dev is a STL-to-GCODE translator for RepRap 3D printers
written by Alessandro Ranellucci <aar@cpan.org> - http://slic3r.org/
Usage: slic3r.pl [ OPTIONS ] [ file.stl ] [ file2.stl ] ...
根据我的研究,我怀疑字符串的空格被用作参数存在一些问题。在尝试此项目之前,我从未使用subprocess
,因此可能会出现简单的语法错误。
我知道Slic3r语法是正确的,因为如果我直接在终端中输入它,它的工作方式就完美了。谁能看到我做错了什么?
答案 0 :(得分:4)
subprocess.Popen
接受args
作为第一个参数。这可以是带有完整命令(包括参数)的 字符串 :
args = "perl /Users/path/to/Slic3r/slic3r.pl --info /Users/path/to/Desktop/STL_Files/GEAR.stl"
pl_script = subprocess.Popen(args, stdout=sys.stdout)
或列表 由实际命令及其所有参数组成(在您的情况下,实际命令为perl
):
args = ["perl",
"/Users/path/to/Slic3r/slic3r.pl",
"--info",
"/Users/path/to/Desktop/STL_Files/GEAR.stl"]
pl_script = subprocess.Popen(args, stdout=sys.stdout)
后者是首选,因为它绕过shell并直接执行perl
。来自文档:
args
应该是一系列程序参数,否则就是一个 串。默认情况下,要执行的程序是args
中的第一项 如果args
是一个序列。如果args
是一个字符串,则解释为 平台依赖并在下面描述。查看shell和可执行文件 与默认行为的其他差异的参数。除非 否则,建议将args
作为序列传递。
(强调我的)
args
列表当然可以使用Python的标准列表操作构建:
base_args = ["perl",
"/Users/path/to/Slic3r/slic3r.pl"]
options = ["--info",
"/Users/path/to/Desktop/STL_Files/GEAR.stl"]
args = base_args + options
args.append("--verbose")
pl_script = subprocess.Popen(args, stdout=sys.stdout)
Sidenote :您撰写了os.system("cd Slic3r")
。这将打开一个shell,更改该shell中的目录 ,然后退出。您的Python脚本仍将在原始工作目录中运行。要更改它,请改用os.chdir("Slic3r")
。 (见here。)
答案 1 :(得分:0)
你也可以使用 shlex 来分解特别是mac或unix中的复杂参数
此处提供更多信息 https://docs.python.org/2/library/shlex.html#shlex.split
e.g。
import shlex, subprocess
args = "perl /Users/path/to/Slic3r/slic3r.pl --info /Users/path/to/Desktop/STL_Files/GEAR.stl"
#using shlex to break down the arguments
mac_arg=shlex.split(args)
#shlex.split will return all the arguments in a list
输出
['perl', '/Users/path/to/Slic3r/slic3r.pl', '--info', '/Users/path/to/Desktop/STL_Files/GEAR.stl']
然后可以进一步与Popen一起使用
p1=Popen(mac_arg)
Shlex 主要优点是您不必担心命令,它总是以Popen接受的方式拆分它们