subprocess.call without command writing to the console [duplicate] - python

This question already has answers here:
How to hide output of subprocess
(5 answers)
Closed 2 years ago.
I am currently writing a python program that contains a section where it pings a target computer to see and it if responds, changes a variable, but when I execute the code the ping command writes to the console (which I don't want).
I have checked the ping commands parameters to see if there is something to make it silent but was unable to find anything. Is there something I can do to stop the command to echoing to the console?
My code below:
if platform.system().lower() == "windows":
parameter = "-n"
else:
parameter = "-c"
exitCode = subprocess.call(f"ping {parameter} 1 {activeConnections[ip][0]}")
if (exitCode == 0):
activeConnections[ip][3] = "T"
activeConnections is a dictionary and if the ping is successful, a value is changed from "F" to "T".

You can use the devnull attribute of the built-in os module:
from os import devnull
from subprocess import STDOUT
# Your code
if platform.system().lower() == "windows":
parameter = "-n"
else:
parameter = "-c"
with open(devnull) as DEVNULL:
exitCode = subprocess.call(f"ping {parameter} 1 {activeConnections[ip][0]}", stdout=DEVNULL, stderr=STDOUT))
if (exitCode == 0):
activeConnections[ip][3] = "T"

Related

Get return value from python script executed with subprocess.Popen [duplicate]

This question already has answers here:
Get a return value using subprocess [duplicate]
(3 answers)
Closed 2 years ago.
I have a main.py that execute file.py using subprocess.Popen:
# Execute request
url = "http://something:50001/dosomething/run"
test = ["python", "file.py", "url", url]
writer = subprocess.Popen(test, shell=False)
File.py execute a function that get an "exit code" when it request the url :
exitCode = None
answer = requests.get(url)
janswer = answer.json()
exitCode = janswer.get("exitCode")
return exitCode
For some reason, I need to execute this file.py using subprocess.Popen so that some code in main.py execute while file.py does its stuff.
What I'm trying to do now is to recover the exitCode from file.py to main.py.
I tried to use stdout=subprocess.Pipe and recover the exit code with a print, but for some reason it doesn't work.
Getting the writer.returncode isn't the solution to because it will give me the code from the subprocess, not from the function
function return exitCode = -2, subprocess return returncode = 0, I need that -2. (-2 is just an example, the exitCode isn't the same all the time and depends on some parameters.)
Here is a short program that illustrates how you can get a number from a subprocess either via pipe or sys.exit(). Note that the range of values that can be returned from sys.exit() is limited, though.
import sys
import subprocess
def sub():
try:
print(42)
except:
# Print something even in case of an exception
print(-1)
raise
sys.exit(43)
def main():
writer = subprocess.Popen(["python3", sys.argv[0], "sub"],
stdout = subprocess.PIPE)
for line in writer.stdout:
print(int(line))
exitcode = writer.wait()
print('exitcode', exitcode)
if len(sys.argv) > 1 and sys.argv[1] == 'sub':
sub()
else:
main()
This prints
42
exitcode 43

Python 3.3+: How to suppress exceptions in subprocess.Popen()?

I have a class with some functions that basically do output checks on data, the functions of this class are called using a subprocess.
Now if the output check fails the subprocess has a sys.exit call with a different code depending on which check it failed.
In the main code I have this:
try:
exitCode = 0
#import module for current test
teststr = os.path.splitext(test)[0]
os.chdir(fs.scriptFolder)
test = __import__(teststr)
#delete old output folder and create a new one
if os.path.isdir(fs.outputFolder):
rmtree(fs.outputFolder)
os.mkdir(fs.outputFolder)
# run the test passed into the function as a new subprocess
os.chdir(fs.pythonFolder)
myEnv=os.environ.copy()
myEnv["x"] = "ON"
testSubprocess = Popen(['python', test.testInfo.network + '.py', teststr], env=myEnv)
testSubprocess.wait()
result = addFields(test)
# poke the data into the postgresql database if the network ran successfully
if testSubprocess.returncode == 0:
uploadToPerfDatabase(result)
elif testSubprocess.returncode == 1:
raise Exception("Incorrect total number of rows on output, expected: " + str(test.testInfo.outputValidationProps['TotalRowCount']))
exitCode = 1
elif testSubprocess.returncode == 2:
raise Exception("Incorrect number of columns on output, expected: " + str(test.testInfo.outputValidationProps['ColumnCount']))
exitCode = 1
except Exception as e:
log.out(teststr + " failed", True)
log.out(str(e))
log.out(traceback.format_exc())
exitCode = 1
return exitCode
Now the output from this shows all traceback and python exceptions for the sys.exit calls in the subprocess.
Im actually logging all errors so I dont want anything being displayed in the command prompt unless ive printed it manually.
I'm not quite sure how to go about this.
You can specify stderr to write to os.devnull with the subprocess.DEVNULL flag:
p = Popen(['python', '-c', 'print(1/0)'], stderr=subprocess.DEVNULL)
subprocess.DEVNULL
Special value that can be used as the stdin, stdout or stderr argument to Popen and indicates that the special file os.devnull will be used.
New in version 3.3. docs

Supress OS command prompt popup in python [duplicate]

This question already has answers here:
Suppressing output in python subprocess call [duplicate]
(2 answers)
Get output of system ping without printing to the console
(2 answers)
Closed 5 years ago.
import subprocess, platform
def ping(host):
args = "ping -n 1 " + host
return subprocess.call(args) == 0
print(ping("www.google.com"))
I am using this code in order to ping a website to test whether it is up or down, which works perfectly, however it results in a command prompt window briefly appearing which is not ideal for what I am working on, so my question is;
How can I supress this window from appearing on pings requests (windows based solution needed)
To use ping to know whether an address is responding, use its return value, which is 0 for success. subprocess.check_call will raise and error if the return value is not 0. To suppress output, redirect stdout and stderr. With Python 3 you can use subprocess.DEVNULL rather than opening the null file in a block.
import os
import subprocess
with open(os.devnull, 'w') as DEVNULL:
try:
subprocess.check_call(
['ping', '-c', '3', '10.10.0.100'],
stdout=DEVNULL, # suppress output
stderr=DEVNULL
)
is_up = True
except subprocess.CalledProcessError:
is_up = False
Ref:Get output of system ping without printing to the console

How can I execute an os/shell command from python [duplicate]

This question already has answers here:
How do I execute a program or call a system command?
(65 answers)
Closed 6 years ago.
For say in terminal I did cd Desktop you should know it moves you to that directory, but how do I do that in python but with use Desktop with raw_input("") to pick my command?
The following code reads your command using raw_input, and execute it using os.system()
import os
if __name__ == '__main__':
while True:
exec_cmd = raw_input("enter your command:")
os.system(exec_cmd)
Best Regards,
Yaron
To go with your specific example, you'd do the following:
import os
if __name__ == "__main__":
directory = raw_input("Please enter absolute path: ")
old_dir = os.getcwd() #in case you need your old directory
os.chdir(directory)
I've used this technique before in some directory maintenance functions I've written and it works. If you want to run shell commands more generally you'd something like:
import subprocess
if __name__ == "__main__":
command_list = raw_input("").split(" ")
ret = subprocess(command_list)
#from here you can check ret if you need to
But beware with this method. The system here has no knowledge about whether it's passing a valid command, so it's likely to fail and miss exceptions. A better version might look like:
import subprocess
if __name__ == "__main__":
command_kb = {
"cd": True,
"ls": True
#etc etc
}
command_list = raw_input("").split(" ")
command = command_list[0]
if command in command_kb:
#do some stuff here to the input depending on the
#function being called
pass
else:
print "Command not supported"
return -1
ret = subprocess(command_list)
#from here you can check ret if you need to
This method represents a list of supported commands. You can then manipulate the list of args as needed to verify it's a valid command. For instance, you can check if the directory you're about to cd exists and return an error to the user if not. Or you can check if the path name is valid, but only when joined by an absolute path.
maybe you can do this:
>>> import subprocess
>>> input = raw_input("")
>>> suprocess.call(input.split()) # for detail usage, search subprocess
for details, you can search subprocess module

Assign output of os.system to a variable and prevent it from being displayed on the screen [duplicate]

This question already has answers here:
Running shell command and capturing the output
(21 answers)
Closed 2 years ago.
I want to assign the output of a command I run using os.system to a variable and prevent it from being output to the screen. But, in the below code ,the output is sent to the screen and the value printed for var is 0, which I guess signifies whether the command ran successfully or not. Is there any way to assign the command output to the variable and also stop it from being displayed on the screen?
var = os.system("cat /etc/services")
print var #Prints 0
From this question 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)
You might also want to look at the subprocess module, which was built to replace the whole family of Python popen-type calls.
import subprocess
output = subprocess.check_output("cat /etc/services", shell=True)
The advantage it has is that there is a ton of flexibility with how you invoke commands, where the standard in/out/error streams are connected, etc.
The commands module is a reasonably high-level way to do this:
import commands
status, output = commands.getstatusoutput("cat /etc/services")
status is 0, output is the contents of /etc/services.
For python 3.5+ it is recommended that you use the run function from the subprocess module. This returns a CompletedProcess object, from which you can easily obtain the output as well as return code. Since you are only interested in the output, you can write a utility wrapper like this.
from subprocess import PIPE, run
def out(command):
result = run(command, stdout=PIPE, stderr=PIPE, universal_newlines=True, shell=True)
return result.stdout
my_output = out("echo hello world")
# Or
my_output = out(["echo", "hello world"])
I know this has already been answered, but I wanted to share a potentially better looking way to call Popen via the use of from x import x and functions:
from subprocess import PIPE, Popen
def cmdline(command):
process = Popen(
args=command,
stdout=PIPE,
shell=True
)
return process.communicate()[0]
print cmdline("cat /etc/services")
print cmdline('ls')
print cmdline('rpm -qa | grep "php"')
print cmdline('nslookup google.com')
I do it with os.system temp file:
import tempfile, os
def readcmd(cmd):
ftmp = tempfile.NamedTemporaryFile(suffix='.out', prefix='tmp', delete=False)
fpath = ftmp.name
if os.name=="nt":
fpath = fpath.replace("/","\\") # forwin
ftmp.close()
os.system(cmd + " > " + fpath)
data = ""
with open(fpath, 'r') as file:
data = file.read()
file.close()
os.remove(fpath)
return data
Python 2.6 and 3 specifically say to avoid using PIPE for stdout and stderr.
The correct way is
import subprocess
# must create a file object to store the output. Here we are getting
# the ssid we are connected to
outfile = open('/tmp/ssid', 'w');
status = subprocess.Popen(["iwgetid"], bufsize=0, stdout=outfile)
outfile.close()
# now operate on the file
from os import system, remove
from uuid import uuid4
def bash_(shell_command: str) -> tuple:
"""
:param shell_command: your shell command
:return: ( 1 | 0, stdout)
"""
logfile: str = '/tmp/%s' % uuid4().hex
err: int = system('%s &> %s' % (shell_command, logfile))
out: str = open(logfile, 'r').read()
remove(logfile)
return err, out
# Example:
print(bash_('cat /usr/bin/vi | wc -l'))
>>> (0, '3296\n')```

Categories