If I run a Python script from Powershell via the call operator ($val = & python myscript.py) – How can I pass in an array to $val from Python?

huangapple go评论123阅读模式
英文:

If I run a Python script from Powershell via the call operator ($val = & python myscript.py) - How can I pass in an array to $val from Python?

问题

以下是已翻译的代码部分:

  1. import os
  2. import sys
  3. import pathlib
  4. import json
  5. from contextlib import redirect_stderr
  6. from fontTools import ttLib
  7. from fontmeta import FontMeta
  8. # 检查命令行参数
  9. if len(sys.argv) == 1:
  10. print('未提供参数。')
  11. exit(0)
  12. fontfile = sys.argv[1]
  13. def font_name(font_path, name_idx):
  14. font = ttLib.TTFont(font_path, ignoreDecompileErrors=True)
  15. with redirect_stderr(None):
  16. names = font['name'].names
  17. details = {}
  18. for x in names:
  19. if x.langID == 0 or x.langID == 1033:
  20. try:
  21. details[x.nameID] = x.toUnicode()
  22. except UnicodeDecodeError:
  23. details[x.nameID] = x.string.decode(errors='ignore')
  24. # details[4] = 全名
  25. # details[1] = 字体族名
  26. # details[2] = 样式名
  27. return details[name_idx]
  28. meta_instance = FontMeta(fontfile)
  29. metadata = meta_instance.get_full_data()
  30. fontFullName = font_name(fontfile, 4)
  31. fontFamily = font_name(fontfile, 1)
  32. fontStyle = font_name(fontfile, 2)
  33. fontVers = metadata[5]['value']
  34. fontVers = fontVers.replace('Version ', "v")
  35. fontLang = metadata[1]['language']['value']
  36. fontUniqueID = metadata[3]['value']
  37. fontPostscriptName = metadata[6]['value']
  38. fontPostscriptEncoding = metadata[6]['encoding']['value']
  39. fontDesigner = metadata[9]['value']
  40. fontLicenseURL = metadata[14]['value']
  41. print('全名: ' + fontFullName)
  42. print('字体族: ' + fontFamily)
  43. print('样式: ' + fontStyle)
  44. print('版本: ' + fontVers)
  45. print('语言: ' + fontLang)
  46. print('唯一标识: ' + fontUniqueID)
  47. print('许可证网址: ' + fontLicenseURL)
  48. print('字体设计师: ' + fontDesigner)

希望这对你有所帮助。如果你需要更多帮助,请随时提问。

英文:

Here's a sample script:

  1. import os
  2. import sys
  3. import pathlib
  4. import json
  5. from contextlib import redirect_stderr
  6. from fontTools import ttLib
  7. from fontmeta import FontMeta
  8. # Check for commandline argument
  9. if len(sys.argv) == 1:
  10. print('No argument was supplied.')
  11. exit(0)
  12. fontfile = sys.argv[1]
  13. def font_name(font_path, name_idx):
  14. font = ttLib.TTFont(font_path, ignoreDecompileErrors=True)
  15. with redirect_stderr(None):
  16. names = font['name'].names
  17. details = {}
  18. for x in names:
  19. if x.langID == 0 or x.langID == 1033:
  20. try:
  21. details[x.nameID] = x.toUnicode()
  22. except UnicodeDecodeError:
  23. details[x.nameID] = x.string.decode(errors='ignore')
  24. # details[4] = Full Name
  25. # details[1] = Family Name
  26. # details[2] = Style Name
  27. return details[name_idx]
  28. meta_instance = FontMeta(fontfile)
  29. metadata = meta_instance.get_full_data()
  30. fontFullName = font_name(fontfile,4)
  31. fontFamily = font_name(fontfile,1)
  32. fontStyle = font_name(fontfile,2)
  33. fontVers = metadata[5]['value'];
  34. fontVers = fontVers.replace('Version ',"v")
  35. fontLang = metadata[1]['language']['value'];
  36. fontUniqueID = metadata[3]['value']
  37. fontPostscriptName = metadata[6]['value']
  38. fontPostscriptEncoding = metadata[6]['encoding']['value']
  39. fontDesigner = metadata[9]['value']
  40. fontLicenseURL = metadata[14]['value']
  41. print('Full Name: ' + fontFullName)
  42. print('Family: ' + fontFamily)
  43. print('Style: ' + fontStyle)
  44. print('Version: ' + fontVers)
  45. print('Language: ' + fontLang)
  46. print('UniqueID: ' + fontUniqueID)
  47. print('License URL: ' + fontLicenseURL)
  48. print('Font Designer: ' + fontDesigner)

Output:

  1. Full Name: Sharp Sans Bold
  2. Family: Sharp Sans
  3. Style: Bold
  4. Version: v1.001
  5. Language: English/United States
  6. UniqueID: 1.001;2016;SHRP;SharpSans-Bold
  7. License URL: http://www.sharptype.co
  8. Font Designer: Lucas Sharp

ps1:

  1. & "D:\Dev\Python\00 VENV\FontTools\Scripts\Activate.ps1"
  2. $val = python "D:\Dev\Python\Font Scripts\GetFontInfo.py" "D:\Fonts\00 Test\SharpSans-Bold.otf"
  3. Write-Host "`$val:" $val -ForegroundColor Green

Right now the Python code is just printing values. My PS script is echoing the printed values as a string. Is there a way to pass these values to powershell other than just printing them - I.E. as an array?

Or should I return JSON and parse it in PowerShell?

Any help appreciated.

答案1

得分: 1

当PowerShell调用一个外部程序时,它会将stdout输出的每一行逐行传送到PowerShell的管道。

如果通过将流捕获到一个变量的赋值来操作这个流:

  • 两行或更多会成为一个数组(类型为[object[]])来存储这些行。

  • 一行会原样存储,作为一个字符串(类型为[string])。

因此:

  1. $val = python "D:\Dev\Python\Font Scripts\GetFontInfo.py" "D:\Fonts\00 Test\SharpSans-Bold.otf"

单独执行上述命令就足以将来自python调用的stdout输出行捕获为一个数组 - 假设有两行或更多

如果您希望确保$val始终是一个数组 - 即使只有一个输出行,您有两个选择:

  1. $val = @(python "D:\Dev\Python\Font Scripts\GetFontInfo.py" "D:\Fonts\00 Test\SharpSans-Bold.otf")
  • 要么:使用一个**[array]类型约束**(等同于[object[]]):
  1. [array] $val = python "D:\Dev\Python\Font Scripts\GetFontInfo.py" "D:\Fonts\00 Test\SharpSans-Bold.otf"

注意

  • 上述两种方法之间存在细微差异 - 详见此答案以获取详细信息。

  • 当PowerShell捕获或重定向来自外部程序的输出时,通常涉及根据存储在[Console]::OutputEncoding中的字符编码进行.NET字符串的解码 - 请参见此答案

  • 要验证$val确实是一个数组,请运行$val.GetType().FullName

  • 要逐行打印每个数组元素,请不要使用Write-Host,只需将$val单独提交(这等同于使用Write-Output $val,尽管后者的显式使用很少需要 - 详见此答案以获取背景信息)。

英文:

When PowerShell invokes an external program, it streams the individual lines of its stdout output one by one to PowerShell's pipeline.

If you capture this stream via assignment to a variable:

  • two or more lines become an array (of type [object[]]) storing the lines.

  • one line is stored as-is, as a string (type [string]).

Therefore:

  1. $val = python "D:\Dev\Python\Font Scripts\GetFontInfo.py" "D:\Fonts\00 Test\SharpSans-Bold.otf"

by itself is sufficient to capture the stdout output lines from your python call as an array - assuming there are two or more lines.

If you want to ensure that $val is always an array - even if there's only one output line, you have two options:

  1. $val = @(python "D:\Dev\Python\Font Scripts\GetFontInfo.py" "D:\Fonts\00 Test\SharpSans-Bold.otf")
  • Or: Use an [array] type constraint (equivalent to [object[]]):
  1. [array] $val = python "D:\Dev\Python\Font Scripts\GetFontInfo.py" "D:\Fonts\00 Test\SharpSans-Bold.otf"

Note:

  • There are subtle differences between the two approaches above - see this answer for details.

  • When PowerShell captures or redirects output from external programs, decoding into .NET strings based on the character encoding stored in [Console]::OutputEncoding is invariably involved - see this answer.

  • To verify that $val is indeed an array, run $val.GetType().FullName.

  • To print each array element on it own line, do not use Write-Host, simply submit $val on its own (which is equivalent to using Write-Output $val, though the latter's explicit use is rarely needed - see this answer for background information.

答案2

得分: 0

你可以按行打印这些值,并按照这里的指示拆分输出:

  1. $arr = $val.Split([Environment]::NewLine)
英文:

You can print the values line by line and split the output by newline as instructed here:

  1. $arr = $val.Split([Environment]::NewLine)

huangapple
  • 本文由 发表于 2023年8月4日 04:57:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76831562.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定