Warm tip: This article is reproduced from serverfault.com, please click

其他-每个PowerShell调用Python脚本并传递PSObject并返回已解析的数据

(其他 - Call Python script per PowerShell & passing PSObject and return the parsed data)

发布于 2020-11-28 11:21:57

一些背景:目前我查询4Mio行(50列)从一个MS SQL服务器dbatools成PSObject(在批10.000行,每行查询),处理使用PowerShell(大量的正则表达式的东西)的数据回写成MariaDb和SimplySql平均而言,我得到约。150行/秒 不得不使用很多技巧(Net的Stringbuilder等)来实现这一性能,它还不错,恕我直言

作为新要求,我想检测某些文本单元格的语言,并且必须删除个人数据(姓名和地址)。为此找到了一些很好的python库(spacypycld2)。我用pycld2进行了测试-很好的检测。

简化代码以进行澄清(提示:我是python noob):

#get data from MS SQL
$data = Invoke-DbaQuery -SqlInstance $Connection -Query $Query -As PSObject -QueryTimeout 1800
for ($i=0;$i -lt $data.length;$i++){
  #do a lot of other stuff here
  #...
  #finally make lang detection
  if ($LangDetect.IsPresent){
    $strLang = $tCaseDescription -replace "([^\p{L}\p{N}_\.\s]|`t|`n|`r)+",""
    $arg = "import pycld2 as cld2; isReliable, textBytesFound, details = cld2.detect('" + $strLang + "', isPlainText = True, bestEffort = True);print(details[0][1])"
    $tCaseLang = & $Env:Programfiles\Python39\python.exe -c $arg
  } else {
    $tCaseLang = ''
  }
}
#write to MariaDB
Invoke-SqlUpdate -ConnectionName $ConnectionName -Query $Query

每次都可以执行此python调用,但是由于每次循环调用和导入pycld2 lib都会破坏性能(12行/秒)。因此,这是一个a脚的解决方案:)此外,如上所述-我想使用spacy-必须解析更多的列才能删除个人数据。

我不确定,是否愿意将整个PS Parser转换为python:|

我相信,更好的解决方案可能是将整个PSObject从PowerShell传递到python(在PS循环启动之前),然后将其以及PSObject(在python中进行处理后)返回,但我不知道如何用python / python函数实现这一点。

你的方法/建议是什么,还有其他想法?谢谢 :)

Questioner
TefoD
Viewed
11
mklement0 2020-11-30 05:30:03

以下简化示例显示了如何将多个[pscustomobject][psobject])实例从PowerShell传递到Python脚本(-c在这种情况下,通过字符串传递):

  • 通过使用JSON作为序列化格式,通过ConvertTo-Json...

  • ...和顺便指出JSON经由管道,其Python可以经由读取标准输入(标准输入)。

重要事项

  • 字符编码

    • $OutputEncoding在将数据发送到外部程序(例如Python)时,PowerShell使用首选项变量中指定的编码,值得称赞的是,在PowerShell [Core] v6 +中该默认值默认为无BOM的UTF-8 ,但在Windows PowerShell中,默认为ASCII(!)

    • 就像PowerShell的限制你发送文本到一个外部程序,它也不可避免地解释它接收文本,即基于存储在编码[Console]::OutputEncoding; 遗憾的是,撰写本文时两个PowerShell版本默认为系统的OEM代码页。

    • 同时发送和接收(BOM-以下)UTF-8将在PowerShell的版本,(临时)组$OutputEncoding[Console]::OutputEncoding如下:
      $OutputEncoding = [Console]::OutputEncoding = [System.Text.Utf8Encoding]::new($false)

  • 如果你希望Python脚本输出对象,请再次考虑使用JSON,你可以在PowerShell上使用JSON将其解析为对象ConvertFrom-Json

# Sample input objects.
$data = [pscustomobject] @{ one = 1; two = 2 }, [pscustomobject] @{ one = 10; two = 20 }

# Convert to JSON and pipe to Python.
ConvertTo-Json $data | python -c @'

import sys, json

# Parse the JSON passed via stdin into a list of dictionaries.
dicts = json.load(sys.stdin)

# Sample processing: print the 'one' entry of each dict.
for dict in dicts:
  print(dict['one'])

'@

如果要传递的数据是单行字符串的集合,则不需要JSON:

$data = 'foo', 'bar', 'baz'

$data | python -c @'

import sys

# Sample processing: print each stdin input line enclosed in [...]
for line in sys.stdin:
  print('[' + line.rstrip('\r\n') + ']')

'@