在命令行中传递密码存在很大的安全风险。具有管理员权限时,可以检索该信息(启动信息对象)并提取密码。更好的解决方案是将7zip作为进程打开,并将密码输入其标准输入。以下是将“source.txt”压缩为“dest.7z”的命令行示例:
CMD = ['c:\\Program Files\\7-Zip\\7z.exe', 'a', '-t7z', '-p', 'c:\\source.txt', 'd:\\dest.7z']
PASSWORD = "Nj@8G86Tuj#a"
首先,您需要将密码转换为输入字符串。请注意,7-zip希望密码在终端中输入。只要这些特殊字符可以在您的终端中表示,就可以使用它们。终端的编码很重要!例如,在匈牙利Windows上,您可能想使用“cp1250”编码。在所有情况下,标准输入是一个二进制文件,并且它期望一个二进制字符串(Python 3中的“bytes”)。如果您想保险起见,可以将密码限制为纯ASCII,并像这样创建您的输入:
input = (PASSWORD + "\r\n").encode("ascii")
如果您知道终端的编码方式,那么可以将密码转换为该编码方式。您还可以检测密码是否无法与系统的编码方式兼容。(顺便提一下,这意味着它也无法交互使用。)
(上次我检查时,Windows 上不同区域设置的终端编码是不同的。也许有一些技巧可以将其更改为 UTF-8,但我不确定如何操作。)
以下是执行命令的方法:
import subprocess
import typing
def execute(cmd : typing.List[str], input: typing.Optional[bytes] = None, verbose=False, debug=False, normal_priority=False):
if verbose:
print(cmd)
creationflags = subprocess.CREATE_NO_WINDOW
if normal_priority:
creationflags |= subprocess.NORMAL_PRIORITY_CLASS
else:
creationflags |= subprocess.BELOW_NORMAL_PRIORITY_CLASS
if debug:
process = subprocess.Popen(cmd, shell=False, stdout=sys.stdout, stderr=sys.stderr, stdin=subprocess.PIPE,
creationflags=creationflags)
else:
process = subprocess.Popen(cmd, shell=False, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
stdin=subprocess.PIPE, creationflags=creationflags)
if input:
process.stdin.write(input)
process.stdin.flush()
returncode = process.wait()
if returncode:
raise OSError(returncode)
CMD = ['c:\\Program Files\\7-Zip\\7z.exe', 'a', '-t7z', '-p', 'c:\\source.txt', 'd:\\dest.7z']
PASSWORD = "Nj@8G86Tuj#a"
input = (PASSWORD + "\r\n").encode("ascii")
execute(CMD, input)
这还展示了如何降低进程优先级(在压缩大量数据时通常是一个好主意),它还展示了如何将标准输出和标准错误转发到控制台。
绝对正确的解决方案是加载7-zip DLL并使用其API。(我没有检查,但可能可以使用8位二进制密码字符串。)
注意:此示例适用于Python 3,但可以使用Python 2完成相同的操作。
subprocess.call(['7z.exe', 'x', '-y', u'-ps^&)kratsaslkd932(lkasdf930¤23', 'file.zip'])
- Kroltan