繁体   English   中英

在 python 中,如何将数组参数传递给 powershell 脚本

[英]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 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM