Python3 sous-processus de sortie
Je suis désireux d'exécuter Linux word count utilitaire wc pour déterminer le nombre de lignes actuellement dans le /var/log/syslog, afin que je puisse détecter qu'il grandit. J'ai essayé de test différents, et alors que je reçois les résultats de wc, il comprend à la fois le nombre de lignes ainsi que la commande (par exemple, la var/log/syslog).
Il est donc de retour:
1338 /var/log/syslog
Mais je veux seulement le nombre de lignes, donc je veux enlever le /var/log/syslog partie, et il suffit de garder 1338.
J'ai essayé de convertir en chaîne de bytestring, puis décapage du résultat, mais pas de joie. Même histoire pour la conversion de chaîne et de décapage, de décodage, etc - tous ne parviennent pas à produire la sortie, je suis à la recherche d'.
Ce sont quelques exemples de ce que je reçois, avec 1338 lignes dans syslog:
- b'1338 /var/log/syslog\n'
- 1338 /var/log/syslog
Voici un code de test que j'ai écrit pour essayer de crack et de cette noix, mais pas de solution:
import subprocess
#check_output returns byte string
stdoutdata = subprocess.check_output("wc --lines /var/log/syslog", shell=True)
print("2A stdoutdata: " + str(stdoutdata))
stdoutdata = stdoutdata.decode("utf-8")
print("2B stdoutdata: " + str(stdoutdata))
stdoutdata=stdoutdata.strip()
print("2C stdoutdata: " + str(stdoutdata))
La sortie de ce est:
-
2A stdoutdata: b'1338 /var/log/syslog\n'
-
2B stdoutdata: 1338 /var/log/syslog
-
2C stdoutdata: 1338 /var/log/syslog
-
2D stdoutdata: 1338 /var/log/syslog
Vous devez vous connecter pour publier un commentaire.
Je vous suggère d'utiliser
subprocess.getoutput()
que c'est exactement ce que vous voulez—exécuter une commande dans un shell et obtenir son sortie de chaîne (par opposition à chaîne d'octets de sortie). Ensuite, vous pouvez split sur les espaces et de saisir le premier élément de la liste retournée de chaînes.Essayez ceci:
subprocess.getoutput
appartient à la catégorie des Héritage Shell Invocation de Fonctions (docs.python.org/3/library/subprocess.html#subprocess.getoutput).subprocess.check_function()
(docs.python.org/3.5/library/...) est mieux de remplacement et aussi nécessite moins de travail. Voir J. F. Sebastian stackoverflow.com/a/18270852/1346705. L'argument peut aussi être une chaîne de caractères.check_output
, pas check_function..?Pour éviter d'appeler un shell et le décodage des noms de fichiers qui pourraient être arbitraire séquence d'octets (sauf
'\0'
) sur *nix, vous pourriez passer le fichier en tant que stdin:Ou vous pouvez ignorer tout des erreurs de décodage:
sys.stdout.encoding
dans ce cas, nous avons donc passer ce à décoder au lieu deascii
? Si noussubprocess.PIPE
stdout ?Depuis Python 3.6 vous pouvez faire
check_output()
retour d'unstr
au lieu debytes
en lui donnant un encodage paramètre:Mais puisque vous voulez juste le comte, et deux
split()
etint()
sont utilisables avecbytes
, vous n'avez pas besoin de s'embêter avec l'encodage:Tandis que certaines choses pourraient être plus facile avec un programme externe (par exemple, le comptage du journal des entrées de ligne imprimée par
journalctl
), dans ce cas particulier, vous n'avez pas besoin d'utiliser un programme externe. Le plus simple Python seule solution est la suivante:Cela ne l'inconvénient qu'il lit tout le fichier en mémoire; si c'est un énorme fichier au lieu d'initialiser
linecount = 0
avant d'ouvrir le fichier et utiliser unfor line in f: linecount += 1
boucle au lieu dereadlines()
d'avoir seulement une petite partie du fichier en mémoire que vous comptez.Équivalent à Curt J. Sampson la réponse est aussi celle-ci (elle retourne une chaîne de caractères):
de docs:
Quelque chose de similaire, mais un peu plus complexe à l'aide de sous-processus.run():
comme sous-processus.check_output() pourrait être l'équivalent de sous-processus.run().