How to do multiple arguments with Python Popen?
To directly answer your question, read below. But there's a lot of problems with your program, some of which I cover in "Better practice."
By default, subprocess.Popen
commands are supplied as a list of strings.
However, you can also you can use the shell
argument to execute a command "formatted exactly as it would be when typed at the shell prompt."
No:
>>> p = Popen("cat -n file1 file2")
Yes:
>>> p = Popen("cat -n file1 file2", shell=True)
>>> p = Popen(["cat", "-n", "file1", "file2"])
There are a number of differences between these two options, and valid use cases for each. I won't attempt to summarize the differences- the Popen
docs already do an excellent job of that.
So, in the case of your commands, you'd do something like this:
cmd = "gnome-terminal -x sudo git clone git://github.com/pererinha/gedit-snippet-jquery.git && sudo cp -f gedit-snippet-jquery/js.xml /usr/share/gedit/plugins/snippets/js.xml && sudo rm -rf gedit-snippet-jquery"
p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT,
close_fds=False)
Better practice
However, using Python as a wrapper for many system commands is not really a good idea. At the very least, you should be breaking up your commands into separate Popens, so that non-zero exits can be handled adequately. In reality, this script seems like it'd be much better suited as a shell script. But if you insist on Python, there are better practices.
The os
module should take the place of calls to rm
and cp
. And while I have no experience with it, you might want to look at tools like GitPython to interact with Git repositories.
Compatibility concerns
Lastly, you should be careful about making calls to gnome-terminal
and sudo
. Not all GNU/Linux users run Ubuntu, and not everyone has sudo
, or the GNOME terminal emulator installed. In its current form, your script will crash, rather unhelpfully, if:
- The
sudo
command is not installed - The user is not in the
sudoers
group - The user doesn't use GNOME, or its default terminal emulator
- Git is not installed
If you're willing to assume your users are running Ubuntu, calling x-terminal-emulator
is a much better option than calling gnome-terminal
directly, as it will call whatever terminal emulator they've installed (e.g. xfce4-terminal
for users of Xubuntu).
Related videos on Youtube
Voidcode
Updated on February 09, 2021Comments
-
Voidcode about 3 years
I am trying to make a PyGtk Gui, that has a button. When the user presses this button,
gnome-terminal
prompts the user to write their password.Then it will clone this Git repository for
gedit
JQuery snippets.And then, it copies the
js.xml
file to/usr/share/gedit/plugins/snippets/js.xml
In the end, it forcefully removes the Git repository.
The command:
gnome-terminal -x sudo git clone git://github.com/pererinha/gedit-snippet-jquery.git && sudo cp -f gedit-snippet-jquery/js.xml /usr/share/gedit/plugins/snippets/js.xml && sudo rm -rf gedit-snippet-jquery
It works fine in my terminal.
But, via the GUI it just opens, I add my password, press enter, and then it closes again.
I'd like to only run the command to the first
&&
This is my Python function (with command):
def on_install_jquery_code_snippet_for_gedit_activate(self, widget): """ Install Jquery code snippet for Gedit. """ cmd="gnome-terminal -x sudo git clone git://github.com/pererinha/gedit-snippet-jquery.git && sudo cp -f gedit-snippet-jquery/js.xml /usr/share/gedit/plugins/snippets/js.xml && sudo rm -rf gedit-snippet-jquery" p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=False) self.status.set_text(p.stdout.read()) #show response in 'status
-
Massimo over 8 yearsavoid string splitting, for shell commands there is shlex.split
-
sandyp about 8 yearsTo add to above, shlex.split() splits the command preserving quoted arguments as is.
-
jfs about 8 yearsdo not pass a list argument with
shell=True
on POSIX (the additional list items are passed to/bin/sh
, not the command -- you don't want it in most cases). Use string instead (i.e., dropshlex.split()
if you useshell=True
) -
David Cain about 8 yearsDuly noted, @J.F.Sebastian. I read the docs again and revised my answer to match the recommendations there. Thanks for pointing that out.
-
JamEngulfer about 8 yearsThis is... Really unhelpful. Why shouldn't we do any of the examples you listed? You provide no actual reasoning to your statements, so why should I believe anything that you're saying?
-
David Cain about 8 years@JamEngulfer - I've now linked to the docs for a thorough explanation of proper syntax of
Popen
. Hope that helps. -
WinEunuuchs2Unix over 3 yearsYour Compatibility concerns is well-taken but could it perhaps be named Cross-Platform Developer Concerns vs. Home User non-concerns or something like that if you get my drift?