首页 > 解决方案 > 将对象从 Python 流式传输到 PowerShell?

问题描述

经过一些搜索和检查以前的答案(如将对象从 python 传递到 powershell)之后,显然将对象从 Python 脚本发送到 PowerShell 脚本或命令的最佳方式将是 JSON。

但是,像这样 ( dir_json.py) :

from json import dumps
from pathlib import Path

for fn in Path('.').glob('**/*'):
    print(dumps({'name': str(fn)}))

你可以这样做:

python .\dir_json.py | ConvertFrom-JSON

结果还可以,但我希望解决的问题是,ConvertFrom-JSON似乎要等到脚本完成后再读取任何 JSON,即使单个 JSON 对象在每一行结束。这可以通过time.sleep(1)在打印后添加一行来轻松验证。

有没有比使用 JSON 对象更好的方法将对象从 Python 发送到 PowerShell?有没有办法在编写它们时实际流式传输它们,而不是在脚本完成后传递 Python 脚本的整个输出?

我遇到了jq,这是“互联网上的人”推荐的解决我的问题类型的方法,指出ConvertFrom-JSON不允许流式传输,但jq可以。但是,这并没有改善我的情况:

python .\dir_json_slow.py | jq -cn --stream 'fromstream(1|truncate_stream(inputs))' | ConvertFrom-JSON

为了让jq游戏变得更好,我确实更改了脚本以编写对象列表而不是单独的对象:

from sys import stdout
from time import sleep
from json import dumps
from pathlib import Path

first = True
stdout.write('[\n')
for fn in Path('.').glob('**/*'):
    if first:
        stdout.write(dumps({'name': str(fn)}))
        first = False
    else:
        stdout.write(',\n'+dumps({'name': str(fn)}))
    stdout.flush()
    sleep(.1)
stdout.write('\n]')

(请注意,问题不ConvertFrom-JSON在于最后,jq它本身仅在 Python 脚本完成后才开始写入输出)

标签: pythonpowershelljq

解决方案


只要您的脚本输出的每一行[1]本身都是一个完整的JSON 对象,您就可以使用调用来处理 PowerShell 接收到的每一行输出并调用每个:pythonForEach-ObjectConvertFrom-Json

python .\dir_json.py | ForEach-Object { ConvertFrom-JSON $_ }

演示发生的简化示例,在处理的行之间暂停(等待按键):

# Prompts for a keystroke after each line emitted by the Python command.
python -c 'from json import dumps; print(dumps({''name'': ''foo''})); print(dumps({''name'': ''bar''}))' | 
  ForEach-Object { ConvertFrom-Json $_ | Out-Host; pause }

注意:该Out-Host调用仅用于解决 PowerShell 中的显示错误,自 PowerShell 7.2 起仍然存在:Out-Host强制同步打印应用的隐式表格格式 - 请参阅此答案


ConvertFrom-Json- 非典型的 PowerShell cmdlet -在发出已解析 JSON 输入的对象之前预先收集所有输入,可演示如下:

# Prompts for a keystroke first, and only after *both*
# strings have been emitted does ConvertFrom-Json produce output.
& { '{ "name": "foo" }'; pause; '{ "name": "bar" }' } |
  ConvertFrom-Json | Out-Host

[1] PowerShell 总是逐行中继来自外部程序(如 Python )的输出。相比之下,PowerShell 原生命令可以自由地将任何对象发送到管道,包括多行字符串。


推荐阅读