在子进程中,某些命令可以工作,但Mac终端没有其他命令

时间:2017-12-28 15:38:29

标签: python macos subprocess popen

我正在尝试创建一个在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语法是正确的,因为如果我直接在终端中输入它,它的工作方式就完美了。谁能看到我做错了什么?

2 个答案:

答案 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接受的方式拆分它们