2009-12-20 7 views
1

Comment effectuer une journalisation de toutes les activités effectuées par un script Python et tous les scripts qui y sont appelés?Sortie de script Python interactif stockée dans un fichier

J'avais plusieurs scripts Bash mais maintenant j'ai écrit un script Python qui appelle tous ces scripts Bash. Je voudrais que toutes les sorties produites à partir de ces scripts soient stockées dans un fichier.

Le script est un script Python interactif, il contient des lignes raw_input, donc je ne peux pas faire comme 'python script.py | tee log.txt 'pour l'ensemble du script Python car pour certaines raisons, les questions ne sont pas visibles à l'écran.

Voici un extrait du script qui appelle l'un des scripts shell.

cmd = "somescript.sh" 
    try: 
    retvalue = subprocess.check_call(cmd, shell=True) 
except subprocess.CalledProcessError: 
    print ("script command has been failed") 
    sys.exit("exit from script") 

Selon vous, que pourrait-on faire ici?

Modifier

Deux sous-questions basées sur la réponse d'Alex:

  1. Comment faire les réponses sur les questions stockées dans le fichier de sortie ainsi? Par exemple sur la ligne ok = raw_input(prompt) l'utilisateur sera demandé pour la question et je voudrais la réponse enregistrée aussi bien.

  2. Je lis à propos de Popen et communique et n'a pas utilisé car il tamponne les données en mémoire. Ici, la quantité de sortie est grande et je dois aussi me soucier de l'erreur standard avec la sortie standard. Savez-vous si cela est possible avec Popen et communiquez avec la méthode?

Répondre

6

Faire propres print s Python vont à la fois le terminal et un fichier est pas difficile:

>>> import sys 
>>> class tee(object): 
... def __init__(self, fn='/tmp/foo.txt'): 
...  self.o = sys.stdout 
...  self.f = open(fn, 'w') 
... def write(self, s): 
...  self.o.write(s) 
...  self.f.write(s) 
... 
>>> sys.stdout = tee() 
>>> print('hello world!') 
hello world! 
>>> 
$ cat /tmp/foo.txt 
hello world! 

Cela devrait fonctionner à la fois en Python 2 et Python 3.

Pour diriger la sortie de la même manière sous-commandes, ne pas utiliser

retvalue = subprocess.check_call(cmd, shell=True) 

qui permet la sortie de cmd aller à sa « sortie standard » régulière, mais plutôt de saisir et réémettre vous-même, comme suit :

p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) 
so, se = p.communicate() 
print(so) 
retvalue = p.returncode 

supposant que vous ne se soucient pas de la norme d'erreur (uniquement-sortie standard) et la quantité de la production de cmd est raisonnablement faible (puisque .communicate tampons que les données en mémoire) - il est facile de modifier si soit l'hypothèse doesn Ne correspond pas à ce que tu veux exactement.

Modifier: l'OP a clarifié les spécifications dans un long commentaire à cette réponse:

  • Comment faire les réponses sur les questions enregistrées dans le fichier de sortie ainsi? Par exemple sur la ligne ok = raw_input (prompt) l'utilisateur sera demandé pour la question et je voudrais comme à la réponse enregistrée aussi bien.

Utilisez une fonction telle que:

def echoed_input(prompt): 
    response = raw_input(prompt) 
    sys.stdout.f.write(response) 
    return response 

au lieu de simplement raw_input dans votre code d'application (bien sûr, cela est écrit spécifiquement à coopérer avec la classe tee je l'ai montré ci-dessus).

  • Je l'ai lu Popen et communiquer et ne pas utiliser les tampons puisqu'il données en mémoire. Ici le montant de la sortie est grand et je dois me soucier de erreur standard avec sortie standard aussi bien. Savez-vous si c'est possible de gérer avec Popen et communiquer aussi bien?

communicate est très bien aussi longtemps que vous ne pas obtenir plus de rendement (et le niveau d'erreur) que se glisse facilement dans la mémoire, dire quelques giga-octets au maximum en fonction du type de machine que vous utilisez.

Si cette hypothèse est satisfaite, tout recoder ce qui précède que, au lieu:

p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, 
        stderr=subprocess.STDOUT) 
so, se = p.communicate() 
print(so) 
retvalue = p.returncode 

dire, juste rediriger se mêler STDERR de la sous-commande dans son stdout.

Si vous avez à vous soucier de giga-octets (ou autre) venant à vous, puis

p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, 
        stderr=subprocess.STDOUT) 
for line in p.stdout: 
    sys.stdout.write(p) 
p.wait() 
retvalue = p.returncode 

(qui obtient et émet une ligne à la fois) peut être préférable (cela dépend de cmd rien attendre de son standard entrée, bien sûr ... parce que, si est s'attendre à quelque chose, il ne va pas l'obtenir, et le problème commence à devenir difficile ;-).

+0

Il y a quelque chose de délicieusement tordu dans votre classe tee(). J'ai clairement passé trop d'années à faire du C (et d'autres langues de dinosaures) avant de venir à la Lumière de Python. –

+0

Salut Alex, merci pour la réponse. J'ai deux sous-questions basées sur votre réponse alors. 1. Comment répondre aux questions stockées dans le fichier de sortie? Par exemple sur la ligne ok = raw_input (prompt) on demandera à l'utilisateur la question et j'aimerais aussi que la réponse soit enregistrée. 2. Je lis à propos de Popen et communique et ne l'utilise pas puisqu'il tamponne les données en mémoire. Ici, la quantité de sortie est grande et je dois aussi me soucier de l'erreur standard avec la sortie standard. Savez-vous si cela est possible avec Popen et communiquez avec la méthode? – yart

+0

@yart, bien sûr, vous pouvez faire tout ce que vous demandez (et il aurait été vraiment merveilleux si vous aviez mis vos spécifications détaillées dans votre question originale, au lieu de nous laisser deviner!), Laissez-moi éditer la réponse (pendant ce temps devrait éditer votre question plutôt que laisser ces détails absolument cruciaux accrocher dans un commentaire!). –

1

Python a un module de suivi: trace. Utilisation: python -m trace --trace file.py

1

Si vous voulez capturer la sortie d'un script, puis sur un * système nix-y vous pouvez rediriger stdout et stderr vers un fichier:

./script.py >> /tmp/outputs.txt 2>> /tmp/outputs.txt 

Si vous voulez tout fini par les scripts, pas seulement ce qu'ils impriment, le module de trace python ne trace pas les choses faites par les scripts externes que votre python exécute. La seule chose qui peut tracer chaque action effectuée par un programme serait quelque chose comme DTrace, si vous êtes assez chanceux pour avoir un système qui le supporte. (OS X Instruments sont basées sur DTrace)

+0

Merci Autopopulated mais la chose que j'ai mentionné que le script est interactif ce qui signifie que vous ne voyez pas avec cette redirection les questions à l'écran. Vous pouvez essayer quelque chose avec ok = raw_input (prompt) dans le script. – yart

Questions connexes