web-dev-qa-db-fra.com

Comment faire plusieurs arguments avec Python Popen?

J'essaie de faire un PyGtk Gui, qui a un bouton. Lorsque l'utilisateur appuie sur ce bouton, gnome-terminal invite l'utilisateur à écrire son mot de passe.

Ensuite, il clonera ce référentiel Git pour gedit extraits JQuery.

Et puis, il copie le js.xml fichier vers /usr/share/gedit/plugins/snippets/js.xml

En fin de compte, il supprime de force le référentiel Git.

La commande:

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

Cela fonctionne bien dans mon terminal.

Mais, via l'interface graphique, il vient d'ouvrir, j'ajoute mon mot de passe, appuyez sur Entrée, puis il se referme.

Je souhaite exécuter la commande uniquement sur le premier &&

Ceci est ma Python (avec commande):

    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
18
Voidcode

Pour répondre directement à votre question, lisez ci-dessous. Mais il y a beaucoup de problèmes avec votre programme, dont certains que je couvre dans "Better practice".


Par défaut, subprocess.Popen les commandes sont fournies sous forme de liste de chaînes.

Cependant, vous pouvez également utiliser l'argument Shell pour exécuter une commande "formatée exactement comme elle le serait lors de la frappe à l'invite du shell".

Non:

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

Oui:

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

Il existe un certain nombre de différences entre ces deux options et des cas d'utilisation valides pour chacune. Je n'essaierai pas de résumer les différences - les Popen docs font déjà un excellent travail.


Donc, dans le cas de vos commandes, vous feriez quelque chose comme ceci:

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)

Meilleure pratique

Cependant, utiliser Python comme wrapper pour de nombreuses commandes système n'est pas vraiment une bonne idée. À tout le moins, vous devriez diviser vos commandes en Popens séparés, afin que les sorties non nulles puissent En réalité, ce script semble être beaucoup mieux adapté en tant que script Shell. Mais si vous insistez sur Python, il existe de meilleures pratiques.

Le module os devrait remplacer les appels à rm et cp. Et même si je n'ai aucune expérience avec cela, vous voudrez peut-être regarder des outils comme GitPython pour interagir avec les référentiels Git.

Problèmes de compatibilité

Enfin, vous devez faire attention à ne pas appeler gnome-terminal et Sudo. Tous les utilisateurs GNU/Linux n'exécutent pas Ubuntu, et tout le monde n'a pas Sudo, ou l'émulateur de terminal GNOME installé. Dans sa forme actuelle, votre script se bloquera, de façon plutôt inutile, si:

  • La commande Sudo n'est pas installée
  • L'utilisateur n'est pas dans le groupe sudoers
  • L'utilisateur n'utilise pas GNOME, ou son émulateur de terminal par défaut
  • Git n'est pas installé

Si vous êtes prêt à supposer que vos utilisateurs exécutent Ubuntu, appelez x-terminal-emulator est une bien meilleure option que d'appeler gnome-terminal directement, car il appellera l'émulateur de terminal installé (par exemple xfce4-terminal pour les utilisateurs de Xubuntu).

52
David Cain