[英]In python, how to pass an array argument to powershell script
我有一个 PowerShell 脚本,它有两个参数,第一个是字符串,第二个是字符串数组。
我想从我的 python 代码中调用这个 PowerShell 脚本。 如何将数组类型参数传递给 PowerShell?
如果我写这样的东西:
subprocess.run(['powershell.exe', 'script.ps1', 'arg1', '@("str1", "str2")'])
Powershell 认为 '@("str1", "str2")' 是一个字符串,而不是一个数组。
编辑我找到了解决方法
subprocess.run(['powershell.exe', 'script.ps1 arg1 @("str1", "str2")'])
它看起来不漂亮,但有效。 这样,我不能在-File
之后使用powershell.exe
您的原始命令确实按书面方式工作(除非您必须使用.\script.ps1
而不是script.ps1
,除非脚本位于系统路径中),您稍后添加的第二个命令也是如此,因为它隐式使用 PowerShell CLI -Command
参数而不是它的
-File
参数。
简而言之:
传递arrays基本上只支持-Command
,它将随后的 arguments 解释为 PowerShell 代码,其中应用通常的 Z3CBC3F9D0CE2F2C1554E1B671D71D9CZ 语法。
相比之下,使用 -File ,目标脚本参数之后的所有-File
都作为字符串逐字传递,因此没有数组的概念。
我建议使用以下方法,以提高稳健性和概念清晰度:
subprocess.run(['powershell.exe', '-noprofile', '-c', '.\script.ps1 arg1 @("str1", "str2")'])
注意:您可以在数组元素周围省略@(...)
- PowerShell 中的数组文字从不需要@()
。
笔记:
-noprofile
确保 PowerShell 不加载$PROFILE
文件,从而避免潜在的减速和副作用。
-c
( -Command
) 明确表明您正在传递PowerShell 代码而不是带有文字 arguments -File
-File ) 的脚本文件
-Command
arguments 会受到 PowerShell 的额外解释,因此,如果您传递一个令牌$foo$
,您打算成为文字,PowerShell 会将其扩展为仅$
(如果没有定义$foo
变量),因为它将$foo
扩展为变量引用; 传递`$foo`$
(反引号转义)可以防止这种情况。 注意script.ps1
之前的.\
:由于您使用的是-Command
,因此您不能仅按文件名执行脚本(除非脚本恰好位于$env:PATH
中列出的目录中); 从 PowerShell 内部,出于安全原因,从当前目录执行脚本需要.\
; 相比之下,仅文件名调用确实适用于-File
。
脚本文件及其 arguments 作为单个参数传递,这反映了 PowerShell 将如何处理命令。
-Command 在Windows PowerShell -Command
是默认的,但在 PowerShell Core ( pwsh.exe
) 中不再是默认的,默认为-File
; 显式使用-Command
( -c
) 或-File
( -f
) 通常是一个好主意,以明确 PowerShell 将如何解释 arguments。
subprocess.run()
如何构建命令行以及 PowerShell 如何解析它: 您原来的 Python 命令将@("str1", "str2")
作为单个参数传递给subprocess.run()
:
subprocess.run(['powershell.exe', '.\script.ps1', 'arg1', '@("str1", "str2")'])
这导致在幕后执行以下命令行:
powershell.exe .\script.ps1 arg1 "@(\"str1\", \"str2\")"
请注意只有@("str1", "str2")
是如何双引号的,以及嵌入的"
字符。如何转义为\"
。
顺便说一句:PowerShell 的CLI (传递给powershell.exe
的参数)使用惯用的\
-转义文字"
字符。;在PowerShell 中,但是,它是`
(反引号)用作转义字符。
您的第二个命令将script.ps1
和@("str1", "str2")
组合成一个参数:
subprocess.run(['powershell.exe', '.\script.ps1 arg1 @("str1", "str2")'])
这将产生以下命令行:
powershell.exe ".\script.ps1 arg1 @(\"str1\", \"str2\")"
注意传递的单个参数是如何作为一个整体被双引号引起来的。
通常,如果 subprocess.run()包含空格,则subprocess.run()
会自动将给定参数括在"..."
(双引号)中。
独立地,它将嵌入的(文字) "
字符。作为\"
。
尽管这些命令行明显不同,PowerShell 的(隐含的) -Command
逻辑对它们的处理是相同的,因为它使用以下算法:
首先,删除每个参数周围的双引号(如果存在)。
结果字符串(如果有多个)用空格连接。
然后将生成的单个字符串作为 PowerShell 代码执行。
如果将此算法应用于上述任一命令行,PowerShell 最终会执行相同的代码,即:
.\script.ps1 arg1 @("str1", "str2")
假设您的 python 阵列是arr
尝试这样做:
subprocess.run(['powershell.exe', 'script.ps1', 'arg1', '\"{}\"'.format(','.join(arr))])
要在 powershell 脚本中发送数组,您可以将其发送为"item1,item2,item3"
,并且 function str.join
允许您轻松获得此格式
如果这不起作用,我会尝试编辑脚本以使用 powershell 脚本中的$args
参数来更改您使用 arguments 的方式
您可以在命令行上使用单引号 - 例如@('str1', 'str2')
或使用反斜杠转义双引号 - 例如@(\"str1\", \"str2\")
例如,使用此脚本:
脚本.ps1
param( [string[]] $s )
write-host $s.GetType().FullName
write-host $s.Length
write-host ($s | fl * | out-string)
您可以像这样从命令提示符调用它:
C:\> powershell.exe .\script.ps1 @('str1', 'str2')
System.String[]
2
str1
str2
或像这样:
C:> powershell.exe .\script.ps1 @(\"str1\", \"str2\")
System.String[]
2
str1
str2
您可能需要应用一些 python 转义字符才能在代码中获得所需的结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.