Assign output of os.system to a variable and prevent it from being displayed on the screen
From "Equivalent of Bash Backticks in Python", which I asked a long time ago, what you may want to use is popen
:
os.popen('cat /etc/services').read()
From the docs for Python 3.6,
This is implemented using subprocess.Popen; see that class’s
documentation for more powerful ways to manage and communicate with
subprocesses.
Here's the corresponding code for subprocess
:
import subprocess
proc = subprocess.Popen(["cat", "/etc/services"], stdout=subprocess.PIPE, shell=True)
(out, err) = proc.communicate()
print "program output:", out
How to store os.system() output in a variable or a list in python
There are many good SO links on this one. try Running shell command from Python and capturing the output or Assign output of os.system to a variable and prevent it from being displayed on the screen for starters. In short
import subprocess
direct_output = subprocess.check_output('ls', shell=True) #could be anything here.
The shell=True flag should be used with caution:
From the docs:
Warning
Invoking the system shell with shell=True can be a security hazard if combined with untrusted input. See the warning under Frequently Used Arguments for details.
See for much more info: http://docs.python.org/2/library/subprocess.html
Python: How to get stdout after running os.system?
If all you need is the stdout
output, then take a look at subprocess.check_output()
:
import subprocess
batcmd="dir"
result = subprocess.check_output(batcmd, shell=True)
Because you were using os.system()
, you'd have to set shell=True
to get the same behaviour. You do want to heed the security concerns about passing untrusted arguments to your shell.
If you need to capture stderr
as well, simply add stderr=subprocess.STDOUT
to the call:
result = subprocess.check_output([batcmd], stderr=subprocess.STDOUT)
to redirect the error output to the default output stream.
If you know that the output is text, add text=True
to decode the returned bytes value with the platform default encoding; use encoding="..."
instead if that codec is not correct for the data you receive.
How would I store the shell command output to a variable in python?
By using module subprocess
. It is included in Python's standard library and aims to be the substitute of os.system
. (Note that the parameter capture_output
of subprocess.run
was introduced in Python 3.7)
>>> import subprocess
>>> subprocess.run(['cat', '/etc/hostname'], capture_output=True)
CompletedProcess(args=['cat', '/etc/hostname'], returncode=0, stdout='example.com\n', stderr=b'')
>>> subprocess.run(['cat', '/etc/hostname'], capture_output=True).stdout.decode()
'example.com\n'
In your case, just:
import subprocess
v = subprocess.run(['cat', '/etc/redhat-release'], capture_output=True).stdout.decode()
Update: you can split the shell command easily with shlex.split
provided by the standard library.
>>> import shlex
>>> shlex.split('cat /etc/redhat-release')
['cat', '/etc/redhat-release']
>>> subprocess.run(shlex.split('cat /etc/hostname'), capture_output=True).stdout.decode()
'example.com\n'
Update 2: os.popen
mentioned by @Matthias
However, is is impossible for this function to separate stdout and stderr.
import os
v = os.popen('cat /etc/redhat-release').read()
Hiding console output produced by os.system
To answer the question based on its title in the most generic form:
To suppress all output from os.system()
, append >/dev/null 2>&1
to the shell command, which silences both stdout and stderr; e.g.:
import os
os.system('echo 3 | sudo tee /proc/sys/vm/drop_caches >/dev/null 2>&1')
Note that os.system()
by design passes output from the calling process' stdout and stderr streams through to the console (terminal) - your Python code never sees them.
Also, os.system()
does not raise an exception if the shell command fails and instead returns an exit code; note that it takes additional work to extract the shell command's true exit code: you need to extract the high byte from the 16-bit value returned, by applying >> 8
(although you can rely on a return value other than 0
implying an error condition).
Given the above limitations of os.system()
, it is generally worthwhile to use the functions in the subprocess
module instead:
For instance, subprocess.check_output()
could be used as follows:
import subprocess
subprocess.check_output('echo 3 | sudo tee /proc/sys/vm/drop_caches', shell=True)
The above will:
- capture stdout output and return it (with the return value being ignored in the example above)
- pass stderr output through; passing
stderr=subprocess.STDOUT
as an additional argument would also capture stderr. - raise an error, if the shell command fails.
Note: Python 3.5 introduced subprocess.run()
, a more flexible successor to both os.system()
and subprocess.check_output()
- see https://docs.python.org/3.5/library/subprocess.html#using-the-subprocess-module
Note:
- The reason that the OP is employing
tee
in the first place - despite not being interested in stdout output - is that a naïve attempt to use> ...
instead would be interpreted beforesudo
is invoked, and thus fail, because the required privileges to write to/proc/sys/...
haven't been granted yet. - Whether you're using
os.system()
or asubprocess
function, stdin is not affected by default, so if you're invoking your script from a terminal, you'll get an interactive password prompt when thesudo
command is encountered (unless the credentials have been cached).
Getting output from os.system (no subprocess)
=> As Martijn Pieters says, there is no way to retrieve the stdout of a os.system() call (because it spawns a subshell = a black box of which we know nothing but its return code). The solution is then to make Python act as a proxy between the final user and CAST3M (pass-through configuration : Python is the "middleman" listening to the user request and transmitting it "as-is" to CAST3M, then capturing CAST3M answer and printing it back to the user). For this, you have to use subprocess, threading and queue modules. If you do not mind the complexity it brings (and the alteration of the original HCI experience), here is a quick summary of links which may reveal usefull :
- Wrap subprocess' stdout/stderr
- Can you make a python subprocess output stdout and stderr as usual, but also capture the output as a string?
- Running an interactive command from within python
- Non-blocking read on a subprocess.PIPE in python
- http://log.ooz.ie/2013/02/interactive-subprocess-communication-in.html
=> Robᵩ provides a workaround for Linux only, by appointing the logging task to the "script" Linux tool. This allows to keep the "user<>CAST3M" interactivity untouched (no proxy here).
How to store executed command (of cmd) into a variable?
Try (for Python3.7+):
import subprocess
data = subprocess.run(["tree", "D://"], capture_output=True)
For Python<3.7:
import subprocess
data = subprocess.run(["tree", "D://"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Related Topics
Changing the "Tick Frequency" on X or Y Axis in Matplotlib
How to Call a Script from Another Script
How Does Assignment Work With List Slices
Most Efficient Way to Map Function Over Numpy Array
Make a Dictionary With Duplicate Keys in Python
How to Clear the Interpreter Console
How to Execute a String Containing Python Code in Python
How to Melt a Pandas Dataframe
Wait Until Page Is Loaded With Selenium Webdriver For Python
Flask View Return Error "View Function Did Not Return a Response"
How to Measure Elapsed Time in Python
How to Fix "Attempted Relative Import in Non-Package" Even With _Init_.Py
Efficient Way to Rotate a List in Python
Unicodeencodeerror: 'Charmap' Codec Can't Encode Characters
Process Escape Sequences in a String in Python
How to Fix: "Unicodedecodeerror: 'Ascii' Codec Can't Decode Byte"
How to Update a Plot in Matplotlib
Are List-Comprehensions and Functional Functions Faster Than "For Loops"