Je souhaite exécuter l'utilitaire de comptage de mots Linux wc pour déterminer le nombre de lignes figurant actuellement dans/var/log/syslog, afin de pouvoir détecter sa croissance. J'ai essayé divers tests et, bien que je récupère les résultats de wc, ils incluent à la fois le nombre de lignes et la commande (par exemple, var/log/syslog).
Alors ça retourne: 1338 /var/log/syslogMais je ne veux que le nombre de lignes, je veux donc supprimer la partie/var/log/syslog et ne garder que 1338.
J'ai essayé de le convertir en chaîne à partir de bytestring, puis de supprimer le résultat, mais pas de joie. Même histoire pour la conversion en chaîne et le stripping, le décodage, etc. - tous ne parviennent pas à produire le résultat recherché.
Voici quelques exemples de ce que je reçois, avec 1338 lignes dans syslog:
Voici un code de test que j'ai écrit pour essayer de résoudre ce problème, 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 ceci est:
2A stdoutdata: b'1338/var/log/syslog\n '
2B stdoutdata: 1338/var/log/syslog
2C stdoutdata: 1338/var/log/syslog
Stdoutdata 2D: 1338/var/log/syslog
Je suggère que vous utilisiez subprocess.getoutput()
car il fait exactement ce que vous voulez - lancez une commande dans un shell et obtenez son string output (par opposition à byte string output). Ensuite, vous pouvez diviser les espaces blancs et récupérer le premier élément de la liste de chaînes renvoyée.
Essaye ça:
import subprocess
stdoutdata = subprocess.getoutput("wc --lines /var/log/syslog")
print("stdoutdata: " + stdoutdata.split()[0])
Pour éviter d'appeler un shell et de décoder des noms de fichiers pouvant être une séquence d'octets arbitraire (à l'exception de '\0'
) sur * nix, vous pouvez transmettre le fichier en tant que stdin:
import subprocess
with open(b'/var/log/syslog', 'rb') as file:
nlines = int(subprocess.check_output(['wc', '-l'], stdin=file))
print(nlines)
Ou vous pouvez ignorer les erreurs de décodage:
import subprocess
stdoutdata = subprocess.check_output(['wc', '-l', '/var/log/syslog'])
nlines = int(stdoutdata.decode('ascii', 'ignore').partition(' ')[0])
print(nlines)
Depuis Python 3.6, vous pouvez demander à check_output()
de renvoyer une str
au lieu de bytes
en lui attribuant un paramètre encoding :
check_output('wc --lines /var/log/syslog', encoding='UTF-8', Shell=True)
Équivalent à la réponse de Curt J. Sampson est également celle-ci (elle renvoie une chaîne):
subprocess.check_output('wc -l /path/to/your/file | cut -d " " -f1', universal_newlines=True, Shell=True)
de docs:
Si un codage ou des erreurs sont spécifiés ou si le texte est true, les objets de fichier pour .__ stdin, stdout et stderr s'ouvrent en mode texte à l'aide du fichier .__ spécifié. codage et erreurs ou la valeur par défaut de io.TextIOWrapper. Le L'argument universal_newlines est équivalent au texte et est fourni pour rétrocompatibilité. Par défaut, les objets de fichier sont ouverts en binaire mode.
Quelque chose de similaire, mais un peu plus complexe en utilisant subprocess.run ():
subprocess.run(command, Shell=True, check=True, universal_newlines=True, stdout=subprocess.PIPE).stdout
as subprocess.check_output () pourrait être équivalent à subprocess.run ().