Run command with sudo from a graphical Python program - python

I want to create a graphical python application that can execute some external programs on Linux without showing the terminal.
First, I tried to use subprocess.run() to see if it actually works, but Python 3.7.3 shows no results to the code I wrote.
import subprocess
subprocess.run(['sudo', 'apt', 'update'])
I changed it to see any results:
import subprocess
a = subprocess.run(['sudo', 'apt', 'update'])
print(a)
but it shows this result instantly:
CompletedProcess(args=['sudo', 'apt', 'update'], returncode=1)
This script will take at least 5 seconds to be finished, and it requires sudo privileges to be able to run it in the first place, so I don't think that Python shell executed this script.

Using pkexec instead of sudo fixed my issue. Thanks for everyone tried to help me especially #Charles Duffy.
Now it looks like this:
import subprocess
result = subprocess.run(['pkexec', 'apt', 'update'], stdout=subprocess.PIPE)
print(result.stdout)

Related

Python script not installing npm package

I have this code here in python
import subprocess
subprocess.Popen(["npm", "install", "express"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
however it doesn't seem to work, it doesn't install anything. When I look at the error it tells me the proper usage of the npm command.
Keep in mind this is on Python 3.8.8 on Ubuntu 18.04
import subprocess
proc = subprocess.Popen(["npm", "install", "express"])
I tested this on Ubuntu 20.04 and it ran the command as expected.
Only thing is that it gets stuck in the NPM process and I've had to press cancel to exit the process.
Instead of using subprocess, Try using os like this:
import os
os.system("npm install express")
os.system("echo You can run commands from terminal using os.")
On my first post destroyer22719 commented:
Hi there! This worked for me, however may I ask how this one works while the other one doesn't? I believe it's important for me that subprocess works.
I would like to say, I never learned how to use subprocess, so I wouldn't know how it works or anything. But, with a little bit of looking around I think I found a solution.
I tested on the latest version of ubuntu as of a week ago (python 3.8.10) and on my windows 10 (python 3.9) and it fails on windows 10 but works on ubuntu.
Ubuntu Version:
import subprocess
from threading import Thread
def package():
subprocess.Popen(["npm install express"], shell=True)
Thread(target=package).start()
print("This text will print if the command is finished or not.")
This is the one that works on windows:
import subprocess
from threading import Thread
def package():
subprocess.Popen(["npm", "install", "express"], shell=True)
Thread(target=package).start()
print("This text will print if the command is finished or not.")
threading is imported because when you run the process it doesn't just stop, so I used Thread() to get around that.

strange problem with running bash-scripts from python in docker

I have python-script, which run bash-scripts via subprocess library. I need to collect stdout and stderr to files, so I have wrapper like:
def execute_chell_script(stage_name, script):
subprocess.check_output('{} &>logs/{}'.format(script, stage_name), shell=True)
And it works correct when I launch my python script on mac. But If I launch it in docker-container (FROM ubuntu:18.04) I cant see any log-files. I can fix it if I use bash -c 'command &>log_file' instead of just command &>log_file inside subprocess.check_output(...). But it looks like too much magic.
I thought about the default shell for user, which launches python-script (its root), but cat /etc/passwd shows root ... /bin/bash.
It would be nice if someone explain me what happened. And maybe I can add some lines to dockerfile to use the same python-script inside and outside docker-container?
As the OP reported in a comment that this fixed their problem, I'm posting it as an answer so they can accept it.
Using check_output when you don't get expect any output is weird; and requiring shell=True here is misdirected. You want
with open(os.path.join('logs', stage_name)) as output:
subprocess.run([script], stdout=ouput, stderr=output)

subprocess and os.system do not work when launched from flask

I need to run a command using python code and I tried to use both os.system and subprocess however both didn't work for some reason. Here's my code:
#app.route('/run-script')
def run_script():
subprocess.call('python3.6 GoReport.py --id 31-33 --format word', cwd="working_dir", shell=True)
return flask.render_template('results.html', **locals())
Running this command from terminal directly works as it should. Trying to reproduce this from python interpreter using command line works as as a charm as well. However it doesn't work when I use Flask. What's the reason for this?
So I've managed to edit my code and import the module instead of using subprocess and os.system. Thanks #tripleee for the explanation!

Using powershell as Admin in python

So I have a project I'm working on, and one thing I need to do is to run in the background the "netstat -nb" command at the PowerShell as admin and recive the results to the python program.
I've been searching the web for a solution but never found one efficient out there. I'd be glad for some help.
"netstat -nb"
If you want to execute the netstat command you can do so from Python directly.But you need to be running Python script as a Admin:
import subprocess
subprocess.call("netstat -nb")
If you need to access the powershell netstat values inside the Python script then you can set variable in powershell and pass it to Python script.
Following is the powershell command:
$con=netstat -nb
& python.exe "FullPath of Python script file"-p $con
Python script:
import sys
print(sys.argv[5])
for conn in sys.argv:
print(conn)
Here we are looping the parameters passed (netstat output) and displaying.So you are passing powershell command result to Python script and displaying it there.
Following columns would be displayed:
You can use subprocess library. About subprocess module you can check this documentation for more detail and features. It helps you to solve your problem. You can use subprocess.Popen or subprocess.call or to get output from another script you can use subprocess.check_output.
You can use it like this piece of code:
import subprocess
import sys
output = subprocess.Popen(['python','sample.py','Hello'],stdout=subprocess.PIPE).communicate()
print(output)
Inside of the sample.py script is:
import sys
my_message = "This is desired output. " + sys.argv[1]
print(my_message)
In your case you can use Popen as:
subprocess.Popen(['netstat','-nb'],stdout=subprocess.PIPE).communicate()

python as a "batch" script (i.e. run commands from python)

I'm working in a windows environment (my laptop!) and I need a couple of scripts that run other programs, pretty much like a windows batch file.
how can I run a command from python such that the program when run, will replace the script? The program is interactive (for instance, unison) and keeps printing lines and asking for user input all the time.
So, just running a program and printing the output won't suffice. The program has to takeover the script's input/output, pretty mcuh like running the command from a .bat file.
I tried os.execl but it keeps telling me "invalid arguments", also, it doesn't find the program name (doesn't search the PATH variable); I have to give it the full path ..?!
basically, in a batch script I can write:
unison profile
how can I achieve the same effect in python?
EDIT:
I found out it can be done with os.system( ... ) and since I cannot accept my own answer, I'm closing the question.
EDIT: this was supposed to be a comment, but when I posted it I didn't have much points.
Thanks Claudiu, that's pretty much what I want, except for a little thing: I want the function to end when the program exits, but when I try it on unison, it doesn't return control to the python script, but to the windows command line environment
>>> os.execlp("unison")
C:\>Usage: unison [options]
or unison root1 root2 [options]
or unison profilename [options]
For a list of options, type "unison -help".
For a tutorial on basic usage, type "unison -doc tutorial".
For other documentation, type "unison -doc topics".
C:\>
C:\>
C:\>
how to get around this?
You should create a new processess using the subprocess module.
I'm not fluent in windows processes but its Popen function is cross-platform, and should be preffered to OS specific solutions.
EDIT: I maintain that you should prefer the Subprocess module to os.* OS specific functions, it is cross-platform and more pythonic (just google it). You can wait for the result easily, and cleanly:
import os
import subprocess
unison = os.path.join(os.path.curdir, "unison")
p = subprocess.Popen(unison)
p.wait()
I found out that os.system does what I want,
Thanks for all that tried to help.
os.system("dir")
runs the command just as if it was run from a batch file
import subprocess
proc = subprocess.Popen(['unison', 'profile'], stderr=subprocess.PIPE,
stdout=subprocess.PIPE, stdin=subprocess.PIPE)
proc.stdin.write('user input')
print proc.stdout.read()
This should help you get started. Please edit your question with more information if you want a more detailed answer!
os.execlp should work. This will search your path for the command. Don't give it any args if they're not necessary:
>>> import os
>>> os.execlp("cmd")
D:\Documents and Settings\Claudiu>Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.
D:\Documents and Settings\Claudiu>

Categories

Resources