Pourquoi utiliser Python module os méthodes au lieu d'exécution de l'interpréteur de commandes directement?
J'essaie de comprendre quelle est la motivation derrière à l'aide de Python à la bibliothèque de fonctions pour l'exécution d'OS tâches spécifiques telles que la création de fichiers/répertoires, modification des attributs de fichier, etc. au lieu de simplement l'exécution de ces commandes via os.system()
ou subprocess.call()
?
Par exemple, pourquoi voudrais-je utiliser os.chmod
au lieu de faire os.system("chmod...")
?
Je comprends que c'est plus "pythonic" utiliser Python est disponible à la bibliothèque de méthodes, autant que possible, au lieu de simplement exécution de l'interpréteur de commandes directement. Mais, est-il un autre motivation derrière de faire cela à partir d'une fonctionnalité de point de vue?
Je ne parle que de l'exécution d'un simple interpréteur de ligne de commandes ici. Lorsque nous avons besoin de plus de contrôle sur l'exécution de la tâche, je comprends que l'utilisation de subprocess
module a plus de sens, par exemple.
- En gros, vous frappez le clou sur la tête. Au niveau de l'OS tâches que vous consultez sont assez communs qu'ils ne le méritent leur propre fonction au lieu d'être simplement relégués à être appelé via le système d'exploitation.système.
- BTW, avez-vous essayer de temps en temps d'exécution du système d'exploitation.chmod vs os.system("chmod..."). Je hasarder une conjecture qu'il répondra à une partie de votre question.
- Pourquoi avoir
print
quand vous pourriezos.system("echo Hello world!")
? - Pour la même raison, vous devez utiliser
os.path
pour gérer les chemins d'accès au lieu de saisir manuellement les manipuler: il fonctionne sur tous les OS dans lequel il s'exécute. - "Exécution de l'interpréteur de commandes directement" est, en réalité, moins directe. Le shell n'est pas une interface de bas niveau pour le système, et
os.chmod
ne va pas à appeler leschmod
programme de la shell. À l'aide deos.system('chmod ...')
lance un shell pour interpréter une chaîne d'appeler un autre fichier exécutable pour faire un appel à la Cchmod
fonction, tandis queos.chmod(...)
va beaucoup plus directement à la Cchmod
. - strictement parlant, il n'est pas nécessairement aller à C de chmod, mais plutôt de faire un chmod syscall. Dans Disponible de cas, il n'est probablement pas ré-écrire le local syscall convention, mais plutôt à réutiliser la bibliothèque C du syscall l'application de la convention, mais d'autres implémentations peuvent éventuellement décider autrement.
Vous devez vous connecter pour publier un commentaire.
C'est plus rapide,
os.system
etsubprocess.call
créer de nouveaux processus qui est inutile pour quelque chose de simple. En fait,os.system
etsubprocess.call
avec leshell
argument généralement de créer au moins deux nouveaux processus: le premier étant la coquille, et la seconde étant la commande que vous utilisez (si ce n'est pas un shell intégré commetest
).Certaines commandes sont inutile dans un processus séparé. Par exemple, si vous exécutez
os.spawn("cd dir/")
, il va changer le répertoire de travail courant du processus enfant, mais pas du Python processus. Vous avez besoin d'utiliseros.chdir
pour que.Vous n'avez pas à vous soucier de spécial caractères interprétés par le shell.
os.chmod(path, mode)
fonctionne, peu importe ce que le nom de fichier, alors que lesos.spawn("chmod 777 " + path)
échouera horriblement si le nom de fichier est quelque chose comme; rm -rf ~
. (Notez que vous pouvez contourner ce problème si vous utilisezsubprocess.call
sansshell
argument.)Vous n'avez pas à vous soucier de les noms de fichiers qui commencent par un tiret.
os.chmod("--quiet", mode)
va changer les permissions du fichier nommé--quiet
, maisos.spawn("chmod 777 --quiet")
échouera, car--quiet
est interprété comme un argument. Cela est vrai même poursubprocess.call(["chmod", "777", "--quiet"])
.Vous avez moins de de la croix-plate-forme et de la croix-shell préoccupations, comme Python standard library est supposée traiter avec que pour vous. Est-ce que votre système de
chmod
commande? Est-il installé? Prend-il en charge les paramètres que vous attendez de soutien? Leos
module va essayer d'être aussi multi-plateforme que possible et de documents lors qu'il n'est pas possible.Si la commande que vous êtes en cours d'exécution a sortie que vous vous souciez, vous devez l'analyser, ce qui est plus compliqué que ça, comme vous pouvez oublier le coin des cas (les noms de fichiers avec des espaces, les tabulations et les retours à la ligne en mer), même lorsque vous ne se soucient pas de la portabilité.
ls
oudir
sont assez haut niveau à certains types de développeurs, tout commebash
oucmd
ouksh
ou quel que soit le shell que vous préférez sont.ls
est de niveau plus élevé que cela, puisqu'il n'est pas un appel direct à votre système d'exploitation noyau de l'API. C'est un (petit) de l'application.ls
oudir
maisopendir()/readdir()
(linux api) ouFindFirstFile()/FindNextFile()
(api windows) ouFile.listFiles
(API java) ouDirectory.GetFiles()
(C#). Tous ces éléments sont étroitement liés à un appel direct à l'OS. Certains peuvent être aussi simple que de pousser un numéro dans un registre et en appelantint 13h
pour déclencher en mode noyau.This module provides a portable way...
docs.python.org/2/library/os.htmlC'est plus sûr. Pour vous donner une idée, voici un exemple de script
Si l'entrée de l'utilisateur a été
test; rm -rf ~
ce serait alors supprimer le répertoire d'accueil.C'est pourquoi il est plus sûr d'utiliser le construit en fonction.
C'est pourquoi vous devriez utiliser des sous-processus au lieu de système de trop.
Il y a quatre forts cas pour préférant Python de plus de méthodes spécifiques dans le
os
module sur l'utilisation deos.système
ou lasous-processus
module lors de l'exécution d'une commande:os
module sont disponibles dans de multiples plates-formes, tandis que de nombreuses commandes shell sont spécifiques aux systèmes d'exploitation.os
module.Redondance (voir code redondant):
Vous êtes réellement l'exécution d'une redondant "middle-man" sur votre chemin à l'éventuel système d'appels (
chmod
dans votre exemple). Cet homme du milieu est un nouveau processus ou d'un sous-shell.De
os.système
:Et
sous-processus
est tout simplement un module de frayer de nouveaux processus.Vous pouvez faire ce que vous avez besoin sans frai de ces processus.
Portabilité (voir code source de la portabilité):
La
os
module vise à fournir générique de système d'exploitation de services et c'est la description commence par:Vous pouvez utiliser
os.listdir
à la fois sur windows et unix. Essayez d'utiliseros.system
/subprocess
pour que cette fonctionnalité va vous forcer à maintenir deux appels (pourls
/dir
) et de vérifier quel système d'exploitation que vous utilisez. Ce n'est pas aussi portable et sera causer encore plus de frustration plus tard (voir gestion de Sortie).La compréhension de la commande de résultats:
Supposons que vous voulez la liste des fichiers dans un répertoire.
Si vous utilisez
os.system("ls")
/subprocess.call(['ls'])
, vous pouvez seulement obtenir le processus de sortie de retour, qui est fondamentalement une grosse chaîne avec les noms de fichier.Comment pouvez-vous dire à un fichier avec un espace dans son nom de deux fichiers?
Que faire si vous n'avez pas l'autorisation d'afficher la liste des fichiers?
Comment mapper les données d'objets python?
Ce sont seulement sur le haut de ma tête, et bien qu'il existe des solutions à ces problèmes - pourquoi résoudre encore un problème qui a été résolu pour vous?
Ceci est un exemple de la suite de la Ne Vous Répétez pas principe (Souvent désigné comme la "SEC") par pas répétition d'une mise en œuvre qui existe déjà et qui est disponible gratuitement pour vous.
De sécurité:
os.system
etsubprocess
sont puissants. C'est bon lorsque vous avez besoin de cette puissance, mais c'est dangereux quand vous n'en avez pas. Lorsque vous utilisezos.listdir
, vous savoir elle ne peut rien faire d'autre, puis d'autres de la liste de fichiers ou de générer une erreur. Lorsque vous utilisezos.system
ousubprocess
pour obtenir le même comportement, vous pouvez éventuellement finir par faire quelque chose que vous ne voulais pas faire.D'Injection de Sécurité (voir shell injection exemples):
Si vous utilisez une entrée de l'utilisateur comme une nouvelle commande vous avez donné de lui une coquille. C'est beaucoup comme l'injection SQL fournir une coquille dans la base de données pour l'utilisateur.
Un exemple serait une commande de la forme:
Ce qui peut être facilement exploitée pour exécuter tout du code arbitraire à l'aide de l'entrée:
NASTY COMMAND;#
pour créer l'éventuelle:Il ya beaucoup de ces commandes qui peuvent mettre votre système en danger.
Pour une raison simple lorsque vous appelez une fonction shell, il crée un sous-shell qui est détruit après votre commande, de sorte que si vous changer de répertoire dans un shell - elle n'affecte pas votre environnement en Python.
En outre, la création de sous-shell est temps de consommer, donc à l'aide d'OS les commandes directement un impact sur votre performance
MODIFIER
J'ai eu quelques synchronisation tests en cours d'exécution:
Interne de la fonction s'exécute plus de 10 fois plus rapide
EDIT2
Il peut y avoir des cas lors de l'appel d'exécutable externe peut donner de meilleurs résultats que les paquets Python - je viens de me rappeler un e-mail envoyé par un de mes collègues que les performances de gzip appelé par le sous-processus a été beaucoup plus élevé que le rendement d'un paquet Python qu'il a utilisés. Mais certainement pas quand on parle de standard de l'OS paquets émulation standard de l'OS commandes
%
au moyen de l'interprète.time <path to script>
dans le terminal et il va vous dire le vrai, les utilisateurs et les processus de temps. C'est si vous n'avez pas de iPython et vous avez accès à la ligne de commande Unix.Coquille d'un appel à l'OS spécifique alors que Python os les fonctions du module sont pas, dans la plupart des cas. Et il éviter la ponte d'un sous-processus.
C'est beaucoup plus efficace. Le "shell" est juste un autre OS binaire qui contient un grand nombre d'appels système. Pourquoi payer les frais généraux de la création de l'ensemble du processus du shell juste pour que seul appel système?
La situation est encore pire lorsque vous utilisez
os.system
pour quelque chose qui n'est pas une coque intégrée. Vous démarrez un processus de shell, qui à son tour commence un exécutable qui ensuite (deux processus de loin) fait l'appel système. Au moinssubprocess
aurait supprimé la nécessité d'une coquille intermédiaire du processus.Ce n'est pas spécifique à Python, c'.
systemd
est une amélioration pour Linux temps de démarrage pour la même raison: il fait le nécessaire appels système lui-même au lieu de pondre un millier d'obus.