140 votes

Comment échapper à l'os.system() appels en Python?

Lors de l'utilisation de l'os.système (), il est souvent nécessaire de s'échapper de noms de fichiers et d'autres arguments passés en paramètres aux commandes. Comment puis-je faire cela? De préférence quelque chose qui pourrait fonctionner sur plusieurs systèmes d'exploitation/coques mais en particulier pour bash.

Je suis actuellement en train de faire la suite, mais je suis sûre qu'il doit être une fonction de la bibliothèque pour cela, ou au moins un de plus élégant/robuste/efficace:

def sh_escape(s):
   return s.replace("(","\\(").replace(")","\\)").replace(" ","\\ ")

os.system("cat %s | grep something | sort > %s" 
          % (sh_escape(in_filename), 
             sh_escape(out_filename)))

Edit: j'ai accepté la réponse la plus simple de l'utilisation des citations, je ne sais pas pourquoi je n'avais pas pensé à ça; je suppose que parce que je venais de Windows où " et " se comporter un peu différemment.

Concernant la sécurité, je comprends l'inquiétude, mais, dans ce cas, je suis intéressé par une solution rapide et facile du système d'exploitation.system() fournit, et la source des cordes n'est pas généré par l'utilisateur, ou au moins entré par un utilisateur de confiance (moi).

177voto

pixelbeat Points 12073

pipes.quote() (disponible depuis le Python 1.6) est-ce que vous voulez.

90voto

Greg Hewgill Points 356191

C'est ce que j'utilise:

def shellquote(s):
    return "'" + s.replace("'", "'\\''") + "'"

Le shell va toujours accepter une cité le nom de fichier et de supprimer l'entourant de guillemets avant de le transmettre au programme en question. Notamment, cela évite les problèmes avec les noms de fichier contenant des espaces ou tout autre type de méchant shell métacaractères.

Udpdate: Si vous utilisez Python 3.3 ou ultérieure, utilisez shlex.citer au lieu de rouler votre propre.

62voto

Jamie Points 1985

Peut-être que vous avez une raison particulière pour l'utilisation de os.system(). Mais si non, vous devriez probablement utiliser l' subprocess module. Vous pouvez spécifier les tuyaux directement et éviter l'utilisation de la coque.

Ce qui suit est PEP324:

Replacing shell pipe line
-------------------------

output=`dmesg | grep hda`
==>
p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
output = p2.communicate()[0]

13voto

Gary Shi Points 344

Peut-être subprocess.list2cmdline est un meilleur coup?

4voto

pauldoo Points 5020

Je crois que les os.système invoque quelle que soit l'interface de commande est configuré pour l'utilisateur, donc je ne pense pas que vous pouvez le faire en une plate-forme indépendante. Ma commande shell pourrait être quelque chose de bash, emacs, ruby, ou même de quake3. Certains de ces programmes ne s'attendent pas le genre d'arguments que vous êtes de passage à eux et même s'ils l'ont fait il n'y a aucune garantie qu'ils ne leur échapper de la même façon.

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