I'm building a cgi script with python on my web host and using wget to test it. The shebang #!/home/me/virtualenv/public_html/chartex/3.6/bin/python3.6
points it at the right version of python to use so that print(sys.version, sys.executable)
in the cgi correctly returns:
3.6.15 (default, Jan 14 2022, 12:16:54)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] /home/me/virtualenv/public_html/chartex/3.6/bin/python3.6_bin
Moreover print(os.path.abspath('.'))
in the cgi returns the correct path to where the script resides.
However, if I want the cgi to report the version of an existing binary on the system print(os.system('twopi -V'))
returns only 0
. The same thing happens doing print(os.system('ls'))
.
If I run the same python installed in this virtualenv (calling it by its full pathname on the server) at the command line, and there call print(os.system('twopi -V'))
, it correctly tells me: twopi - graphviz version 4.0.0 (20220529.0937)
and then on the next line: 0
. Likewise if I do print(os.system('ls'))
Is this kind of system command impossible for a cgi script? Is there a way I can coerce the script to report the result of such a system command?
In case anyone is similarly confused about subprocess
:
Thanks to the observations of @furas and a great deal of messing about with subprocess
I finally figured out an incantation that would compel my python2.7 cgi script to give me the shell output of the command twopi -V
. A comment from @tripleee in this thread was the key. For Python 3.7.9 and up: "capture_output
is a shorthand for the option combination stdout=supprocess.PIPE, stderr=subprocess.PIPE
p = subprocess.Popen(['twopi', '-V'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print("stderr: " + p.stderr.read())
print("stdout: " + p.stdout.read())
# with the result:
stderr: twopi - graphviz version 4.0.0 (20220529.0937)
stdout:
The actual shell output was going to stderr
. The subprocess
module is byzantine! It's a little better under python3, but not much.