Lorsque vous essayez d'écrire la sortie standard d'un script Python dans un fichier texte ( python script.py > log
), le fichier texte est créé au démarrage de la commande, mais le contenu réel n'est pas écrit jusqu'à la fin du script Python. Par exemple:
script.py:
import time
for i in range(10):
print('bla')
time.sleep(5)
Imprime vers stdout toutes les 5 secondes lorsqu'il est appelé avec python script.py
, mais lorsque j'appelle python script.py > log
, la taille du fichier journal reste égale à zéro jusqu'à la fin du script. Est-il possible d'écrire directement dans le fichier journal, de sorte que vous puissiez suivre la progression du script (par exemple, utiliser tail
)?
EDIT Il s'avère que ça python -u script.py
fait l'affaire, je ne connaissais pas la mise en tampon de stdout.
Réponses:
Cela se produit car, normalement, lorsque le processus STDOUT est redirigé vers autre chose qu'un terminal, la sortie est alors stockée dans une mémoire tampon de la taille d'un système d'exploitation (4 ou 8k dans certains cas). Inversement, lors de la sortie vers un terminal, STDOUT sera mis en mémoire de ligne ou pas du tout, de sorte que vous verrez la sortie après chaque
\n
ou pour chaque caractère.Vous pouvez généralement changer la mise en mémoire tampon STDOUT avec l'
stdbuf
utilitaire:Maintenant, si vous
tail -F log
, vous devriez voir chaque ligne sortie immédiatement comme elle est générée.De même, un vidage explicite du flux de sortie après chaque impression devrait permettre d'obtenir le même résultat. Il semble que cela
sys.stdout.flush()
devrait atteindre cela en Python. Si vous utilisez Python 3.3 ou plus récent, laprint
fonction a aussi unflush
mot - clé qui fait cela:print('hello', flush=True)
.la source
python -u script.py
c'était la solution. EDIT Tant de réponses à la fois, j’ai accepté la tienne car elle m’a orienté dans la direction de la mise en mémoire tampon.--line-buffered
pourgrep
, mais d'autres pas.stdbuf
est l'utilitaire général fourre-tout pour traiter ceux qui ne le font pas.stdbuf -o0 python script.py > log
à- dire dans ce genre de circonstances déterminées?-oL
est un compromis. En général, des mémoires tampons plus grandes offrent de meilleures performances lors de la redirection quelque part (moins d'appels système et moins d'opérations d'E / S). Cependant, s'il est absolument nécessaire de voir chaque caractère lors de la sortie, alors oui,-o0
il sera requis.Cela devrait faire le travail:
Comme Python va mettre le tampon
stdout
par défaut, j'ai utilisé icisys.stdout.flush()
pour vider le tampon.Une autre solution consisterait à utiliser le
-u
commutateur (non tamponné) depython
. Donc, ce qui suit fera aussi:la source
Une variation sur le thème de l'utilisation de l'option propre de python pour une sortie non tamponnée consisterait à utiliser
#!/usr/bin/python -u
comme première ligne.Avec
#!/usr/bin/env python
cet argument supplémentaire, ça ne marchera pas, alors alternativement, on pourrait courirPYTHONUNBUFFERED=1 ./my_scriipt.py > output.txt
ou le faire en deux étapes:la source
Vous devriez passer
flush=True
à laprint
fonction:Selon la documentation, par défaut,
print
n'impose rien au nettoyage:Et la documentation pour
sys
les strems dit:Si vous êtes coincé avec une ancienne version de python, vous devez appeler la
flush
méthode dusys.stdout
flux:la source
DigitalTrauma
10 heures avant. Vous devriez upvoter son post, ne pas poster la même chose à nouveau.print(flush=True)
été ajoutée à cette réponse après la mienne par un auteur tiers. Je trouve cela de mauvais goût d'extraire le contenu de ma réponse pour les mettre dans un autre sans crédit. J'ai décidé d'ajouter ma réponse uniquement parce qu'aucune réponse ne mentionnait le moyen le plus simple de réaliser ce que le PO souhaitait dans les versions plus récentes de Python, et j'ai ajouté le "moyen ancien" juste pour être complet. La prochaine fois, veuillez vérifier l'historique des révisions avant de commenter et / ou de voter.__future__
importation:from __future__ import print_function
. Mais oui, c'est uniquement pour la compatibilité avec Python 3