如何用 Python Popen 做多个参数?
问题描述
我正在尝试制作一个带有按钮的 PyGtk Gui.当用户按下此按钮时,gnome-terminal
提示用户输入密码.
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.
然后它将为 gedit
JQuery 片段.
Then it will clone this Git repository for gedit
JQuery snippets.
然后,它将 js.xml
文件复制到 /usr/share/gedit/plugins/snippets/js.xml
And then, it copies the js.xml
file to /usr/share/gedit/plugins/snippets/js.xml
最后,它强行删除了 Git 存储库.
In the end, it forcefully removes the Git repository.
命令:
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.
但是, 通过它刚刚打开的 GUI,我添加了我的密码,按 Enter,然后它再次关闭.
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 &&
这是我的 Python 函数(带命令):
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
解决方案
要直接回答您的问题,请阅读下文.但是您的程序存在很多问题,其中一些我在更好的实践"中进行了介绍.
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."
默认情况下,subprocess.Popen
命令以字符串列表的形式提供.
By default, subprocess.Popen
commands are supplied as a list of strings.
但是,您也可以使用 shell
参数来执行格式与在 shell 提示符下键入时完全一样"的命令.
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."
否:
>>> p = Popen("cat -n file1 file2")
是的:
>>> p = Popen("cat -n file1 file2", shell=True)
>>> p = Popen(["cat", "-n", "file1", "file2"])
这两个选项之间存在许多差异,并且每个选项都有有效的用例.我不会试图总结差异 - Popen
docs 在这方面已经做得很好了.
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)
更好的做法
但是,使用 Python 作为许多系统命令的包装器并不是一个好主意.至少,您应该将命令分解为单独的 Popen,以便可以充分处理非零退出.实际上,这个脚本似乎更适合作为 shell 脚本.但如果你坚持使用 Python,还有更好的做法.
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.
os
模块 应该代替调用到 rm
和 cp
.虽然我没有这方面的经验,但您可能想看看像 GitPython 这样的工具来与 Git 存储库交互.
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.
最后,你应该小心调用 gnome-terminal
和 sudo
.并非所有 GNU/Linux 用户都运行 Ubuntu,也不是每个人都安装了 sudo
或 GNOME 终端仿真器.在当前形式下,如果出现以下情况,您的脚本将会崩溃,而且毫无帮助:
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:
sudo
命令未安装- 用户不在
sudoers
组中 - 用户未使用 GNOME 或其默认终端模拟器
- Git 未安装
如果您愿意假设您的用户正在运行 Ubuntu,那么调用 x-terminal-emulator
比直接调用 gnome-terminal
更好,因为它将调用他们安装的任何终端模拟器(例如,Xubuntu 用户的 xfce4-terminal
).
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).
相关文章