如何在 Python 中的随机文件上安全地调用类型?

How to call type safely on a random file in Python?

所以我试图在某个任意文件上调用 Windows 命令类型。不幸的是,每当我将 cmd 从 shell 命令转换为非 shell 命令时,它都会失败。因此,我无法使用推荐的方法来确保我的 python 脚本不会被利用。这是一个例子。

import subprocess
cmd = "type" + '"' + "some_file_with_no_spaces_or_other_things_wrong" + '"'
p = subprocess.pOpen(cmd, shell = True)

但是当我尝试时:

#Assume cmd split is done properly. Even when I manually put in the 
#array with properly escaped quotes it does not work
subprocess.pOpen(cmd.split(), shell = False)

失败了,不知道怎么解决。我希望能够通过将 shell 设置为 false 来安全地调用此命令,但是每当我这样做时,我都会收到以下错误。

Traceback (most recent call last):
  File "C:\Users\Skylion\git\LVDOWin\Bin\Osiris.py", line 72, in openFileDialog
    stderr = STDOUT, shell = False, bufsize = 0, universal_newlines=True)
  File "C:\Python34\lib\subprocess.py", line 859, in __init__
    restore_signals, start_new_session)
  File "C:\Python34\lib\subprocess.py", line 1112, in _execute_child
    startupinfo)
FileNotFoundError: [WinError 2] The system cannot find the file specified

请注意,即使 运行ning: subprocess.Popen(['type']) 会抛出错误。我的问题是如何清理文件名,以便我可以 运行 使用 shell=True 的文件名,或者让 shell=False 正常工作。

如能提供有关如何以这种方式正确打开文件的任何帮助,我们将不胜感激。

type 是内部命令,因此您需要 运行 cmd.exe 例如,隐式地通过 shell=True.

如果在 Windows 上将命令作为列表传递,则调用 subprocess.list2cmdline() 将列表转换为字符串以传递给 CreateProcess() Windows API.它的语法不同于 cmd.exe 语法。详情请见.

将 shell 命令作为字符串传递并添加 shell=True:

from subprocess import check_call

check_call(r'type "C:\path\with spaces & special symbols.txt"', shell=True)

注意:r'' 前缀用于避免转义文字字符串中的反斜杠。

如果命令在命令行中按原样工作,那么它也应该在Python中工作。

如果文件名在变量中给出,那么您可以使用 ^:

将其转义为 shell cmd
escaped_filename = filename_with_possible_shell_meta_chars.replace("", "^")[:-1]
check_call('type ' + escaped_filename, shell=True)

注意:没有明确的引号。

显然,您可以在纯 Python:

中模拟 type 命令

TYPE copies to the console device (or elsewhere if redirected). No check is made that the file is readable text.

如果您只需要读取一个文件;使用 open() 函数:

with open(r'C:\path\with spaces & special symbols.txt', 
          encoding=character_encoding) as file:
    text = file.read()

如果您不指定显式编码,则 open() 使用 ANSI 代码页,例如 'cp1252' (locale.getpreferredencoding(False)) 将文件内容解码为 Unicode 文本。

注意:您必须在此处考虑 4 个字符编码:

  1. 文本文件本身的字符编码。它可以是任何东西,例如 utf-8
  2. GUI 应用程序使用的 ANSI 代码页,例如 notepad.exe 例如 cp1252cp1251
  3. cmd.exe 使用的 OEM 代码页,例如 cp437cp866。它们可用于 type 命令重定向时的输出
  4. utf-16 由 Unicode API 使用,例如 WriteConsoleW() 例如,当使用 cmd /U 开关时。注意:Windows 控制台显示 UCS-2,即仅支持 BMP Unicode 字符,但复制粘贴甚至适用于 😊 (U+1F60A).
  5. 等星体字符

参见 Keep your eye on the code page

要将 Unicode 打印到 Windows 控制台,请参阅