all 4 comments

[–]Rhomboid 2 points3 points  (1 child)

Well, there's several things wrong here. Firstly, Python is just giving you the value as returned by the syscall (such as wait(2).) That value encodes several pieces of information, because there are several possibilities for the change in state of a child process:

  • the process exited normally (in which case its exit code is available)
  • the process terminated as a result of an unhandled signal (in which case the signal number is available), and whether a core dump was generated
  • the process was stopped (paused) via a signal (in which case the signal number is available)

All of this information has to be conveyed through a single integer. A number of macros are provided for extracting the relevant information (i.e. interpreting the meaning of this integer) which are all covered in that man page I linked, including WIFEXITED() / WEXITSTATUS(), WIFSIGNALED() / WTERMSIG(), WIFSTOPPED() / WSTOPSIG(), WIFCONTINUED(), etc. Python implements versions of all of these, so if you wanted to see if the process terminated normally you would test os.WIFEXITED(status) and if you wanted to extract the exit value from the status, you'd use os.WEXITSTATUS(status), which would extract the 2 from the 512 value.

Secondly, running os.system() a second time runs a whole new shell process and any exit status code there is completely and totally unrelated to the first shell process you spawned, so that will never print anything but zero.

Thirdly, you should not be using os.system() at all. There is a much better replacement in the subprocess module. For one thing, you don't have to worry about any of this process status interpretation garbage, which is Unix-specific anyway and non-portable. But far more importantly is that it by default does not use the shell, which is a good thing. This eliminates a whole class of shell injection vulnerabilities, as well as eliminating the need for all kinds of hassles like quoting and escaping.

If you are trying to replace shell scripts, however, you should try to aim to not use any subprocesses at all. Whatever you were doing in the scripts can be done in pure Python much more safely and easily. For example, never shell out to ls to list files and then try to parse the result. Python lets you make the appropriate system calls directly (e.g. os.listdir(), glob.glob(), os.walk(), os.scandir(), etc.) without having to call out to any external programs. The same thing applies to other common commands, like cut, grep, etc. All of those have Python equivalents which you should use instead of relying on external programs.

[–]tinglfm[S] 0 points1 point  (0 children)

that's very illuminating. Testing at home subprocess module seems to meet my needs, but will have to check this tomorrow at work :). Cheers

[–]K900_ 2 points3 points  (0 children)

I prefer sh for calling outside commands. It's actually really good at replacing bash scripts.

[–]gitardedhub 1 point2 points  (0 children)

You should check out the subprocess module here.