【问题标题】:Encoding issue while running Sysinternals Autorunsc via Python subprocess通过 Python 子进程运行 Sysinternals Autorunsc 时出现编码问题
【发布时间】:2017-06-12 22:16:46
【问题描述】:

我有一个 Python 3.6.0 脚本,我在系统上运行 autorunsc v13.71 (https://technet.microsoft.com/en-us/sysinternals/bb963902.aspx)(x86 或 x86_64 版本,根据使用 platform.machine() 的系统位数)。如果我直接从终端(CMD 或 Powershell)运行autorunsc,我会按预期得到输出,没有问题(从输出中截取):

但是,如果我尝试使用我的代码运行它,我会得到这个混乱的输出:

我正在使用 Window 的默认记事本打开输出文本文件。人们应该可以使用记事本阅读它,他们将无法下载 Notepad++、ST3 等代码阅读器。


我的代码(删除了一些部分以使其简短直接):

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import platform
import socket
import subprocess
from time import gmtime, strftime
from pathlib import Path

HOSTNAME = socket.gethostname()
SYS_ARCH = platform.machine()  # AMD64 or x86
ROOT_PATH = Path(__file__).parent


def get_current_datetime():
    return strftime("%Y-%m-%d %H:%M:%S UTC%z", gmtime())


def run_command(output_file, command_name, command_args, system_cmd=False):
    output_file.write(f'---------- START [{command_name} {SYS_ARCH}] {get_current_datetime()} ----------\n')
    output_file.flush()

    file_path = command_name if system_cmd else str(ROOT_PATH / 'tools' / SYS_ARCH / (command_name + '.exe'))
    subprocess.call([file_path] + command_args, stdout=output_file, shell=True, universal_newlines=True)

    output_file.write(f'---------- ENDED [{command_name} {SYS_ARCH}] {get_current_datetime()} ----------\n\n')
    output_file.flush()
    print(f'[*] [{command_name} {SYS_ARCH}] done')


def main():
    output_file = ROOT_PATH.parent / (HOSTNAME + '.txt')
    with open(output_file, 'w', encoding='utf-8') as fout:
        run_command(output_file=fout, command_name='autorunsc', command_args=['-h', '-nobanner', '-accepteula'])


if __name__ == '__main__':
    main()

文件结构:

  • 文件夹\
    • app.py(此处显示的代码)
    • 工具\
      • AMD64\
        • autorunsc.exe
      • x86\
        • autorunsc.exe

我相信这与 autorunsc 的输出有关,我在某处读到它返回编码为 UTF-16 的输出。问题是我运行了许多其他 Sysinternals EXE 并将输出附加到同一个文件(使用我的 run_command 函数),并且所有这些都可以完美地工作,但是这个。我怎样才能做到这一点?

【问题讨论】:

    标签: python sysinternals


    【解决方案1】:

    要在 Microsoft 记事本中打开文件,您必须使用 Microsoft 换行符:\r\n (CR LF)。

    Python 3 中的 open 函数有一个 newline 参数。

    您可以像这样修复您的代码:

    with open(output_file, 'w', encoding='utf-8', newline='\r\n') as fout:
        run_command(output_file=fout, command_name='autorunsc', command_args=['-h', '-nobanner', '-accepteula'])
    

    【讨论】:

    • 没有解决问题。得到同样混乱的输出。所有其他输出的换行符都很好。 autorunsc 不是我使用我的代码运行的唯一 .exe,我还运行了其他 Sysinternals 工具并且输出格式正确。
    • 您可以使用splitlines 拆分为您的命令的输出,然后将它们写入您的文件中。
    • 不,我不能,看看subprocess.call([file_path] + command_args, stdout=output_file, stderr=output_file, shell=True, universal_newlines=True)。它会自动发送到输出到文件 (output_file)。我无法控制线条。
    • 您的屏幕副本似乎有一个BOM。并且可能是用 UTF16 编码的。
    • 使用check_output代替call获取子进程输出。
    【解决方案2】:

    我找到了解决方案。实际上,问题在于autorunsc 工具输出的编码。它在UTF16,其余的是UTF8,这就是我所做的:

    # IF-ELSE to handle the 'autorunsc' output, which is UTF16
    if command_name == 'autorunsc':
        result = subprocess.Popen([file_path] + command_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        text = result.stdout.read().decode('UTF16')
        for line in text:
            output_file.write(line)
    else:
        subprocess.call([file_path] + command_args, stdout=output_file, stderr=output_file) 
    

    使用此代码,我可以在单个 UTF-8 file.txt 中包含所有输出。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-16
      • 2014-03-17
      • 2019-03-19
      • 2012-12-25
      相关资源
      最近更新 更多