提问人:Norbert Yuhas 提问时间:9/20/2023 最后编辑:Norbert Yuhas 更新时间:9/21/2023 访问量:54
python3 PowerShell stdout 西里尔语编码
python3 powershell stdout cyrillic encoding
问:
我需要执行以下操作:我通过 ssh 从 Python 连接到 Windows 服务器,并在其上运行 powershell 命令。我需要从该服务器获得响应并进一步使用它。 如果我提出这样的请求:
command_company = (
'powershell.exe -noprofile -command "'
'Get-ADUser -Filter \\"sAMAccountName -like \'j.d\'\\" -Properties sAMAccountName, Mobile | Select-Object -ExpandProperty Mobile"'
)
然后一切都对我有用,我得到了一个手机号码。 如果我确实喜欢这样:
command_company = (
'powershell.exe -noprofile -command "'
'Get-ADUser -Filter \\"sAMAccountName -like \'j.d\'\\" -Properties sAMAccountName, Company | Select-Object -ExpandProperty Company"'
)
那么我没有收到错误:
powershell.exe -noprofile -command "Get-ADUser -Filter \"sAMAccountName -like 'j.d'\" -Properties sAMAccountName, Company | Select-Object -ExpandProperty Company"
env: {}, command: powershell.exe -noprofile -command "Get-ADUser -Filter \"sAMAccountName -like 'j.d'\" -Properties sAMAccountName, Company | Select-Object -ExpandProperty Company", subsystem: None, exit_status: None, exit_signal: None, returncode: None, stdout: , stderr:
Output:
Exit Code: None
我猜这可能是 powershell 发送的响应的编码问题。 如果我直接在 PS 中执行请求
Get-ADUser -Filter "sAMAccountName -like 'j.d'" -Properties sAMAccountName, Company | Select-Object -ExpandProperty Company
我得到答案:
PS C:\Windows\system32> C:\ServiceScripts\Test.ps1
ООО МерседесБенцРус
如何更改响应编码?
完整代码:
async def run_ssh_command(user_login):
async with asyncssh.connect(edited) as conn:
command_company = (
'powershell.exe -noprofile -command "'
'Get-ADUser -Filter \\"sAMAccountName -like \'j.d\'\\" -Properties sAMAccountName, Company | Select-Object -ExpandProperty Company"'
)
print(command_company)
result = await conn.run(command_company)
print(result)
output_company = result.stdout
exit_code = result.exit_status
print(f"Output: {output_company}")
print(f"Exit Code: {exit_code}")
await client.send_message(chat_id, f'From: {output_company}', reply_to=reply_to_msg_id)
return output_company
答:
我用paramiko替换了ssh,选择了cp866作为编码 在此版本中,一切正常:
async def run_ssh_command(user_login):
client = paramiko.SSHClient()
try:
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('Edited')
command_company = (
'powershell.exe -noprofile -command "'
'Get-ADUser -Filter \'sAMAccountName -like \'\'{0}\'\'\' -Properties sAMAccountName, Company | Select-Object -ExpandProperty Company"'.format(user_login)
)
print(command_company)
stdin, stdout, stderr = client.exec_command(command_company)
output_company = stdout.read().decode('cp866')
exit_code = stdout.channel.recv_exit_status()
print(f"Output: {output_company}")
print(f"Exit Code: {exit_code}")
return output_company
except Exception as e:
print(f"An error occurred: {str(e)}")
return None
finally:
client.close()
通过切换到不同的 SSH 库,您似乎找到了解决方案,该库允许您指定用于解码显式接收的 stdout 输出的字符编码。
让我补充一些背景信息......
...并提供可能适用于您的原始代码的 Python v3+ 解决方案:我不知道 SSH 如何影响这一点(您的原始库 asyncsh 声称使用 UTF-8),但下面的示例代码肯定适用于使用 UTF-8 的本地 PowerShell 调用,如图所示。
两个版本中的 PowerShell CLI(适用于 Windows PowerShell.exe 的 PowerShell
、适用于 PowerShell (Core) 7+ 的 pwsh.exe
) ) 基于活动(输出)控制台代码页(默认为系统的 OEM 代码页)对其 stdout 输出进行编码。
如果不想对其进行硬编码,就像在代码中一样,可以使用以下命令来确定它:
from ctypes import windll; cp = windll.kernel32.GetConsoleOutputCP()
如果要改用 UTF-8(如果 PowerShell 命令输出无法在 OEM 代码页中表示的字符),则必须使用 UTF-8,可以执行以下操作:
import subprocess
import sys
from ctypes import windll
# Sample text containing an ASCII char.,
# a non-ASCII char that can be mapped onto at least some OEM code pages,
# and one that cannot.
text = 'e€╳'
# A sample PowerShell command that simply echoes the text.
command = f"powershell.exe -noprofile -c '{text}'"
# Save the current console output code page and temporarily change it to
# UTF-8 (65001)
oldCp = windll.kernel32.GetConsoleOutputCP()
windll.kernel32.SetConsoleOutputCP(65001)
# Call the PowerShell CLI, which now emits UTF-8 text.
# Note the use of .decode(), which is based on sys.getdefaultencoding(),
# which is UTF-8 in v3+, and the .strip() call to remove a trailing newline.
out = subprocess.run(command, stdout=subprocess.PIPE).stdout.decode().strip()
# Restore the previous output console code page.
windll.kernel32.SetConsoleOutputCP(oldCp)
# Print the captured output and its byte representation.
print('received text: ' + out)
print(out.encode()) # byte representation
注意:
以上仅确保 PowerShell 子进程发出 UTF-8,并且其输出在 Python 进程中解码,这与 Python 本身用于其输出流的字符编码无关。
要将 Python v3.7+ 本身置于 Python UTF-8 模式,使其将输入解码为 UTF-8 并生成 UTF-8 输出,请传递命令行选项或定义值为 before 调用的环境变量。
-X utf8
PYTHONUTF8
1
(仅)如果这样做,则上述调用的替代方法是将作为附加参数传递给调用。
.decode()
text=True
subprocess.run()
独立地,作为附加参数传递而不是调用也是一种选择。
encoding='utf-8'
.decode()
上一个:C# 不可逆字符串编码转换
下一个:如何转换存储的错误编码数据?
评论