英文:
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?
问题
以下是已翻译的代码部分:
import os
import sys
import pathlib
import json
from contextlib import redirect_stderr
from fontTools import ttLib
from fontmeta import FontMeta
# 检查命令行参数
if len(sys.argv) == 1:
print('未提供参数。')
exit(0)
fontfile = sys.argv[1]
def font_name(font_path, name_idx):
font = ttLib.TTFont(font_path, ignoreDecompileErrors=True)
with redirect_stderr(None):
names = font['name'].names
details = {}
for x in names:
if x.langID == 0 or x.langID == 1033:
try:
details[x.nameID] = x.toUnicode()
except UnicodeDecodeError:
details[x.nameID] = x.string.decode(errors='ignore')
# details[4] = 全名
# details[1] = 字体族名
# details[2] = 样式名
return details[name_idx]
meta_instance = FontMeta(fontfile)
metadata = meta_instance.get_full_data()
fontFullName = font_name(fontfile, 4)
fontFamily = font_name(fontfile, 1)
fontStyle = font_name(fontfile, 2)
fontVers = metadata[5]['value']
fontVers = fontVers.replace('Version ', "v")
fontLang = metadata[1]['language']['value']
fontUniqueID = metadata[3]['value']
fontPostscriptName = metadata[6]['value']
fontPostscriptEncoding = metadata[6]['encoding']['value']
fontDesigner = metadata[9]['value']
fontLicenseURL = metadata[14]['value']
print('全名: ' + fontFullName)
print('字体族: ' + fontFamily)
print('样式: ' + fontStyle)
print('版本: ' + fontVers)
print('语言: ' + fontLang)
print('唯一标识: ' + fontUniqueID)
print('许可证网址: ' + fontLicenseURL)
print('字体设计师: ' + fontDesigner)
希望这对你有所帮助。如果你需要更多帮助,请随时提问。
英文:
Here's a sample script:
import os
import sys
import pathlib
import json
from contextlib import redirect_stderr
from fontTools import ttLib
from fontmeta import FontMeta
# Check for commandline argument
if len(sys.argv) == 1:
print('No argument was supplied.')
exit(0)
fontfile = sys.argv[1]
def font_name(font_path, name_idx):
font = ttLib.TTFont(font_path, ignoreDecompileErrors=True)
with redirect_stderr(None):
names = font['name'].names
details = {}
for x in names:
if x.langID == 0 or x.langID == 1033:
try:
details[x.nameID] = x.toUnicode()
except UnicodeDecodeError:
details[x.nameID] = x.string.decode(errors='ignore')
# details[4] = Full Name
# details[1] = Family Name
# details[2] = Style Name
return details[name_idx]
meta_instance = FontMeta(fontfile)
metadata = meta_instance.get_full_data()
fontFullName = font_name(fontfile,4)
fontFamily = font_name(fontfile,1)
fontStyle = font_name(fontfile,2)
fontVers = metadata[5]['value'];
fontVers = fontVers.replace('Version ',"v")
fontLang = metadata[1]['language']['value'];
fontUniqueID = metadata[3]['value']
fontPostscriptName = metadata[6]['value']
fontPostscriptEncoding = metadata[6]['encoding']['value']
fontDesigner = metadata[9]['value']
fontLicenseURL = metadata[14]['value']
print('Full Name: ' + fontFullName)
print('Family: ' + fontFamily)
print('Style: ' + fontStyle)
print('Version: ' + fontVers)
print('Language: ' + fontLang)
print('UniqueID: ' + fontUniqueID)
print('License URL: ' + fontLicenseURL)
print('Font Designer: ' + fontDesigner)
Output:
Full Name: Sharp Sans Bold
Family: Sharp Sans
Style: Bold
Version: v1.001
Language: English/United States
UniqueID: 1.001;2016;SHRP;SharpSans-Bold
License URL: http://www.sharptype.co
Font Designer: Lucas Sharp
ps1:
& "D:\Dev\Python\00 VENV\FontTools\Scripts\Activate.ps1"
$val = python "D:\Dev\Python\Font Scripts\GetFontInfo.py" "D:\Fonts\00 Test\SharpSans-Bold.otf"
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]
)。
因此:
$val = python "D:\Dev\Python\Font Scripts\GetFontInfo.py" "D:\Fonts\00 Test\SharpSans-Bold.otf"
单独执行上述命令就足以将来自python
调用的stdout输出行捕获为一个数组 - 假设有两行或更多。
如果您希望确保$val
始终是一个数组 - 即使只有一个输出行,您有两个选择:
- 要么:使用**
@(...)
,即数组子表达式运算符:
$val = @(python "D:\Dev\Python\Font Scripts\GetFontInfo.py" "D:\Fonts\00 Test\SharpSans-Bold.otf")
- 要么:使用一个**
[array]
类型约束**(等同于[object[]]
):
[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:
$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:
- Either: Use
@(...)
, the array-subexpression operator:
$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[]]
):
[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 usingWrite-Output
$val
, though the latter's explicit use is rarely needed - see this answer for background information.
答案2
得分: 0
你可以按行打印这些值,并按照这里的指示拆分输出:
$arr = $val.Split([Environment]::NewLine)
英文:
You can print the values line by line and split the output by newline as instructed here:
$arr = $val.Split([Environment]::NewLine)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论