2010-11-03 21 views
6

J'ai un tas de print appels que j'ai besoin d'écrire dans un fichier au lieu de stdout. (Je n'ai pas du tout besoin de stdout.)impression dans un fichier en Python: redirect vs argument du fichier d'impression vs écriture

Je considère trois approches. Y a-t-il des avantages (y compris la performance) pour chacun d'entre eux?

redirect pleine, que j'ai vu here:

import sys 

saveout = sys.stdout 
fsock = open('out.log', 'w') 
sys.stdout = fsock 

print(x) 
# and many more print calls 

# later if I ever need it: 
# sys.stdout = saveout 
# fsock.close() 

Redirect dans chaque déclaration d'impression:

fsock = open('out.log', 'w') 
print(x, file = fsock) 
# and many more print calls 

fonction Write:

fsock = open('out.log', 'w') 
fsock.write(str(x)) 
# and many more write calls 
+0

si vous utilisez py3k read [diveintopython 3] (http://diveintopython3.org/) – SilentGhost

+0

oublié d'ajouter que j'ai posé une question connexe il y a peu de temps. http://stackoverflow.com/questions/4090652/where-to-store-a-log-file-name-in-python – max

+0

En cas de doute, profil. http://docs.python.org/py3k/library/profile.html –

Répondre

6

Je ne m'attendrais à aucune différence de performance durable parmi ces approches. L'avantage de la première approche est que tout code qui se comporte raisonnablement bien (modules que vous importez) prendra automatiquement la redirection désirée.

La deuxième approche n'a aucun avantage. C'est seulement approprié pour le débogage ou le code jetable ... et même pas une bonne idée pour cela. Vous voulez que vos décisions de sortie soient consolidées dans quelques endroits bien définis, pas dispersés dans votre code dans tous les appels à print(). En Python3 print() est une fonction plutôt qu'une déclaration. Cela vous permet de le redéfinir, si vous le souhaitez. Donc vous pouvez def print(*args) si vous voulez. Vous pouvez également appeler le __builtins__.print() si vous avez besoin d'y accéder, dans la définition de votre propre print() personnalisé, par exemple. La troisième approche ... et par extension le principe que toutes vos sorties doivent être générées dans des fonctions spécifiques et des méthodes de classe que vous définissez à cette fin ... est probablement le meilleur.

Vous devriez garder votre sortie et votre formatage séparés de votre fonctionnalité principale autant que possible. En les gardant séparés, vous permettez à votre noyau d'être réutilisé. (Par exemple, vous pouvez commencer par quelque chose qui doit être exécuté à partir d'une console texte/shell, et qui doit ensuite fournir une interface utilisateur Web, une interface frontale plein écran (curses) ou une interface graphique. autour de ...dans les situations où les données résultantes doivent être renvoyées sous leur forme native (en tant qu'objets) plutôt que d'être insérées en tant que texte (sortie) et réparties dans de nouveaux objets. Par exemple, j'ai eu plus d'une occasion où quelque chose que j'ai écrit pour effectuer des requêtes complexes et la collecte de données à partir de diverses sources et imprimer un rapport ... dire des divergences ... plus tard besoin d'être adapté dans un formulaire qui pourrait cracher les données sous une forme (telle que YAML/JSON) qui pourrait être introduite dans un autre système (par exemple, pour rapprocher une source de données par rapport à une autre.)

Si, d'emblée, vous gardez la principale opérations distinctes de la sortie et de la mise en forme, ce type d'adaptation est relativement facile, sinon cela implique un peu de refactoring (parfois une réécriture complète)

4

A partir des noms de fichiers que vous utilisez dans votre question, il semble que vous vouliez créer un fichier journal. Avez-vous considéré le module Python logging à la place?

+0

voir l'historique récent de l'OP – SilentGhost

+0

Finalement, j'ai décidé de ne pas utiliser 'logging'. J'ai plusieurs fichiers à écrire, et je l'ai trouvé plus facile à gérer par moi-même. Mais merci, je vais le garder à l'esprit. – max

4

Je pense que la sémantique est imporant:

je suggère première approche pour la situation lorsque vous l'impression de la même chose que vous imprimez à la console. La sémantique sera la même. Pour une situation plus complexe, j'utiliserais un module de journalisation standard.

La deuxième et la troisième approche sont un peu différentes si vous imprimez des lignes de texte. Deuxième approche - print ajoute le retour chariot et write non.

J'utiliserais la troisième approche en écrivant principalement le format binaire ou non-textuel et j'emploierais la redirection dans la déclaration d'impression dans la plupart des autres cas.

+1

+1: info de nouvelle ligne. – max