【问题标题】:How to do multiple arguments with Python Popen?如何用 Python Popen 做多个参数?
【发布时间】:2012-07-02 07:19:18
【问题描述】:

我正在尝试制作一个带有按钮的 PyGtk Gui。当用户按下此按钮时,gnome-terminal 会提示用户输入密码。

然后它将为gedit JQuery sn-ps 克隆这个Git repository

然后,它将js.xml 文件复制到/usr/share/gedit/plugins/snippets/js.xml

最后,它强行删除了 Git 存储库。

命令:

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

它在我的终端上运行良好。

但是, 通过它刚刚打开的 GUI,我添加了我的密码,按 Enter,然后它再次关闭。

我只想将命令运行到第一个&&

这是我的 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

【问题讨论】:

    标签: python pygtk subprocess popen gnome-terminal


    【解决方案1】:

    要直接回答您的问题,请阅读下文。但是您的程序存在很多问题,其中一些我在“更好的实践”中进行了介绍。


    默认情况下,subprocess.Popen 命令以字符串列表的形式提供。

    但是,您也可以使用 shell 参数来执行“格式与在 shell 提示符下键入时完全一样”的命令。

    否:

    >>> p = Popen("cat -n file1 file2")
    

    是的:

    >>> p = Popen("cat -n file1 file2", shell=True)
    >>> p = Popen(["cat", "-n", "file1", "file2"])
    

    这两个选项之间存在许多差异,并且每个选项都有有效的用例。我不会试图总结这些差异——Popen docs 已经做得很好了。


    所以,对于你的命令,你会做这样的事情:

    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,还有更好的做法。

    os module 应该代替对rmcp 的调用。虽然我没有这方面的经验,但您可能希望查看像 GitPython 这样的工具来与 Git 存储库进行交互。

    兼容性问题

    最后,打电话给gnome-terminalsudo 时要小心。并非所有 GNU/Linux 用户都运行 Ubuntu,也不是每个人都安装了 sudo 或 GNOME 终端仿真器。在当前形式下,如果出现以下情况,您的脚本将会崩溃,而且毫无帮助:

    • sudo 命令未安装
    • 用户不在sudoers 组中
    • 用户未使用 GNOME 或其默认终端仿真器
    • Git 未安装

    如果您愿意假设您的用户正在运行 Ubuntu,则调用 x-terminal-emulator 比直接调用 gnome-terminal 更好,因为它将调用他们安装的任何终端模拟器(例如,xfce4-terminal 用户Xubuntu)。

    【讨论】:

    • 避免字符串拆分,shell命令有shlex.split
    • 添加到上面,shlex.split() 将命令拆分为原样保留引用的参数。
    • 不要在 POSIX 上使用shell=True 传递列表参数(the additional list items are passed to /bin/sh, not the command——在大多数情况下你不需要它)。改用字符串(即,如果使用 shell=True,则删除 shlex.split()
    • 注意到了,@J.F.Sebastian。我再次阅读the docs 并修改了我的答案以匹配那里的建议。感谢您指出这一点。
    • 这……真的没用。为什么我们不应该做你列出的任何例子?你没有为你的陈述提供任何实际的推理,所以我为什么要相信你所说的任何事情?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多