Closed jngrad closed 4 months ago
@jngrad I have checked the current main and I think that we have got rid of all calls to os.system
in our library during the last PRs. I will inforce the use of subprocess
from now on in new developments. If you agree, I would just close this issue.
I would strongly recommend moving away from
os.system()
(which directly exposes the shell), in favor of safer and more interoperable alternatives, namelysubprocess.check_output()
(shell=False
is default),tempfile.TemporaryDirectory()
,os.makedirs()
,shutil.move()
,glob.glob()
.Rules for escaping characters with special meaning in paths (e.g. whitespace, slashes) are cumbersome and easy to forget;
subprocess
does all that for us. When interrupting a Python script that callsos.system()
in a loop (e.g. the testsuite), the interrupt signal is forwarded to the subprocess without affecting the main process; hence the subprocess is interrupted but the main process continues iterating the loop. Withsubprocess.check_output()
, the signal interrupts the subprocess and the main process (via aKeyboardInterrupt
that can be caught and gracefully handled by atry ... except
clause). When a shell command fails,os.system()
silently ignores the issue: it returns an OS-specific error code, and Python continues executing the code; here is a somewhat contrived example:Output:
Note that
subprocess.run()
won't raise an exception: it returns an object that wraps the exception and provides more info, such as the error code and the command line arguments, to help the user diagnose the issue. Also, some of therm path/*
commands can probably be replaced with a temporary folder context manager, which is automatically cleaned up when leaving the context manager.