路径示例:C:\Users\user\Some Space\dev\sensor\
def readSensorList():
with open('sensor.json') as json_data:
data = json.load(json_data)
json_data.close()
return data
def executeSensor():
sensorList = list()
sensorListRaw = readSensorList()
for sensor in sensorListRaw['sensors']:
x = [subprocess.Popen(['powershell.exe','-ExecutionPolicy', 'Unrestricted', sensorListRaw["path"] + sensor["filename"], "-name", sensor["name"]], stdout=subprocess.PIPE, stderr=subprocess.PIPE), sensor["name"]]
sensorList.append(x)
return sensorList
Json包含路径:
{
"path": "C:\\Users\\\\sensor\\",
"sensors":
[{
"name": "partition",
"filename": "partition.ps1"
}]
}
在我的测试环境中,路径中没有空间,但是现在,在生产中,我在路径中有一些空间,而且我对如何使用空间和参数从python执行powershell脚本毫无头绪
我试着引用这条路,没有任何成功。
编辑:我确定问题来自powershell.exe命令,而不是来自python,因为:
powershell.exe -ExecutionPolicy 'Unrestricted C:\Users\some space\Desktop\PythonSensor\sensor\sensor.ps1'
不要在CMD中工作。
答案 0 :(得分:2)
问题不仅在于Python,还在于Windows。内部类Unix系统使用execve
系统调用,该调用将(路径)可执行文件和将传递给命令的参数作为参数。
在Windows中,系统API具有函数CreateProcess
,该函数将可执行文件的路径和整个命令行作为参数作为单个字符串。然后由子进程决定解析命令行以查找其参数
Python尽最大努力遵循Windows内部使用来构建一个将按预期解析的命令行,但只要一个参数包含双引号("
),它就会失败。
例如,如果foo.bat
是一个带有3个参数的批处理脚本,那么这是正确的:
proc = subprocess.Popen(('foo.bat', 'a', 'b c', 'd'),
stdout= subprocess.PIPE, stderr=subprocess.PIPE)
foo将收到3个参数,a
,b c
和d
。
但是如果你使用:
proc = subprocess.Popen(('foo.bat', '"a"', '"b c"', '"d"'),
stdout= subprocess.PIPE, stderr=subprocess.PIPE)
foo将收到4个参数:"a"
,"b
,c"
和"d"
。
TL / DR:您必须确保包含空格的参数的字符串不包含在"
答案 1 :(得分:2)
我终于找到了,你必须把'放在这样的空间之间:
powershell -command "C:\Users\me\Desktop\test\ps' 'test.ps1"
在python中:
subprocess.Popen(['powershell','-ExecutionPolicy', 'Unrestricted', '-command', path]
路径为:
C:\Users\me\Desktop\some' 'space\sensor\
没有“正如Serge Ballesta解释的那样。”
答案 2 :(得分:1)
尽管在Windows上确实处理参数/参数有点不一致,但在这种情况下这不是问题。 Pythons submodule.Popen
正确处理(基于these rules)。 (Serge Ballesta调用.bat
文件的示例并不合适,因为.bat
文件由cmd.exe
执行而cmd.exe
几乎是目前唯一的应用程序不遵循these rules。)
在这种情况下的问题是使用-Command
:
使用-Command
参数调用PowerShell时,所有后续参数都会连接到单个命令(如$args -join " "
)。然后执行该命令。
-Command
是默认参数:如果参数不以-
或/
开头,则powershell会表现出来,就像之前存在-Command
一样。
此:
subprocess.Popen(['powershell.exe', r'C:\Users\user\Some Space\dev\sensor\partition.ps1', "-name", "partition"])
因此,等同于交互式PowerShell会话中的此命令:
C:\Users\user\Some Space\dev\sensor\partition.ps1 -name partition
如果用引号包围每个空格(如您自己的答案中所述),则生成的powershell命令为:
C:\Users\user\Some' 'Space\dev\sensor\partition.ps1 -name partition
这是允许的并且有效 - 但如果您的路径包含其他特殊字符,例如$
或`
,它将再次中断。它也会破坏
script参数包含空格或其他特殊字符。
<强> TL;博士强>:
要从powershell外部正确调用powershell脚本,请使用-File
参数:
subprocess.Popen(['powershell.exe','-ExecutionPolicy', 'Unrestricted', '-File', sensorListRaw["path"] + sensor["filename"], "-name:", sensor["name"]])
-File
之后的参数是脚本名称(没有任何其他奇怪的转义),所有以下参数都是脚本的参数。
请注意:
附加到参数名称(-name:
而不是-name
) - 在大多数情况下,它也可以在没有:
的情况下工作,但如果相应的值以短划线开头,没有:
就会失败。