78 votes

utilisation des caractères génériques des sous-processus

import os

import subprocess

proc = subprocess.Popen(['ls','*.bc'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

out,err = proc.communicate()

print out

Ce script devrait imprimer tous les fichiers avec le suffixe .bc mais il retourne une liste vide. Si je fais ls *.bc manuellement dans la ligne de commande, cela fonctionne. Faire ['ls', 'test.bc'] à l'intérieur du script fonctionne également mais pour une raison quelconque, le symbole de l'étoile ne fonctionne pas Une idée ?

96voto

Niklas B. Points 40619

Vous devez fournir shell=True pour exécuter la commande via un interpréteur de commandes. Cependant, si vous faites cela, vous ne pouvez plus fournir une liste comme premier argument, car les arguments seront alors cités. A la place, spécifiez la ligne de commande brute telle que vous voulez qu'elle soit passée à l'interpréteur de commandes :

 proc = subprocess.Popen('ls *.bc', shell=True,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)

1 votes

Merci, cela a bien fonctionné. Certains des exemples que j'ai trouvés sur Internet avaient une liste comme premier argument pour une raison quelconque.

17 votes

@Cemre : C'est généralement conseillé car vous Ne le fais pas. veulent que l'interpréteur de commandes interprète les arguments. Imaginons que vous passiez l'entrée utilisateur à une commande comme dans 'ls ' + user_supplied_path . L'utilisateur pourrait simplement saisir le chemin ; shutdown -s et le système s'arrêtait ! Si vous utilisez ['ls', user_supplied_path] vous évitez ce genre d'injection.

2 votes

Dans le cas dynamique, cela peut être très dangereux. Popen("ls " + filename, shell=True) où le nom de fichier est égal à blahblah; rm -rf / . Voici ma variante

69voto

dbr Points 66401

Élargir le * glob fait partie du shell, mais par défaut subprocess fait no envoyer vos commandes via un shell, donc la commande (premier argument, ls ) est exécuté, alors un littéral * est utilisé comme argument.

C'est une bonne chose. le bloc d'avertissement dans la section "Arguments fréquemment utilisés". de la documentation sur les sous-processus. Il traite principalement des implications en matière de sécurité, mais peut également aider à éviter les erreurs de programmation stupides (puisqu'il n'y a pas de caractères magiques de l'interpréteur de commandes à prendre en compte).

Mon principal reproche à l'égard de shell=True c'est qu'il implique généralement qu'il y a une meilleure façon de résoudre le problème - dans votre exemple, vous devriez utiliser el glob module :

import glob
files = glob.glob("*.bc")
print files # ['file1.bc', 'file2.bc']

Cette méthode sera plus rapide (pas de frais de démarrage de processus), plus fiable et multiplateforme (elle ne dépend pas de la présence d'une fonction ls commande)

0 votes

subprocess does not send your commands via a shell Pourquoi ? Pouvez-vous fournir une référence ? Merci

1 votes

De plus, cela donne un objet python avec lequel travailler et manipuler. Ce devrait être la réponse choisie. Beaucoup plus python amicale.

1 votes

@Alston The subprocess la documentation documente très clairement la signification de shell=True et comment le défaut est shell=False . Voir aussi stackoverflow.com/questions/3172470/

2voto

Extended Range Points 55

En plus de faire shell=True Assurez-vous également que votre chemin n'est pas cité. Sinon, il ne sera pas développé par le shell.

Si votre chemin d'accès peut contenir des caractères spéciaux, vous devrez les échapper manuellement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X