There is a big security risk in passing the password on the command line. With administrative rights, it is possible to retrieve that information (startup info object) and extract the password. A better solution is to open 7zip as a process, and feed the password into its standard input.
Here is an example of a command line that compresses "source.txt" into "dest.7z":
CMD = ['c:\\Program Files\\7-Zip\\7z.exe', 'a', '-t7z', '-p', 'c:\\source.txt', 'd:\\dest.7z']
PASSWORD = "Nj@8G86Tuj#a"
First you need to convert the password into an input string. Please note that 7-zip expects the password to by typed into the terminal. You can use special characters as long as they can be represented in your terminal. The encoding of the terminal matters! For example, on Hungarian Windows, you might want to use "cp1250" encoding. In all cases, the standard input is a binary file, and it expects a binary string ("bytes" in Python 3). If you want to be on the safe side, you can restrict passwords to plain ascii and create your input like this:
input = (PASSWORD + "\r\n").encode("ascii")
If you know the encoding of your terminal, then you can convert the password to that encoding. You will also be able to detect if the password cannot be used with the system's encoding. (And by the way, it also means that it cannot be used interactively either.)
(Last time I checked, the terminal encoding was different for different regional settings on Windows. Maybe there is a trick to change that to UTF-8, but I'm not sure how.)
This is how you execute a command:
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)
This also shows how to lower process priority (which is usually a good idea when compressing large amounts of data), and it also shows how to forward standard output and standard error to the console.
The absolute correct solution would be to load 7-zip DLL and use its API. (I did not check but that can probably use 8 bit binary strings for passwords.)
Note: this example is for Python 3 but the same can be done with Python 2.