306 votes

Comment rediriger la sortie 'print' vers un fichier ?

Je veux rediriger l'impression vers un fichier .txt en utilisant Python. J'ai un for boucle, qui print la sortie pour chacun de mes fichiers .bam alors que je veux rediriger todo dans un seul fichier. J'ai donc essayé de mettre :

f = open('output.txt','w')
sys.stdout = f

au début de mon script. Cependant, je n'obtiens rien dans le fichier .txt. Mon script est :

#!/usr/bin/python

import os,sys
import subprocess
import glob
from os import path

f = open('output.txt','w')
sys.stdout = f

path= '/home/xxx/nearline/bamfiles'
bamfiles = glob.glob(path + '/*.bam')

for bamfile in bamfiles:
    filename = bamfile.split('/')[-1]
    print 'Filename:', filename
    samtoolsin = subprocess.Popen(["/share/bin/samtools/samtools","view",bamfile],
                                  stdout=subprocess.PIPE,bufsize=1)
    linelist= samtoolsin.stdout.readlines()
    print 'Readlines finished!'

Alors quel est le problème ? Un autre moyen que celui-ci sys.stdout ?

Je veux que mon résultat ressemble à :

Filename: ERR001268.bam
Readlines finished!
Mean: 233
SD: 10
Interval is: (213, 252)

449voto

Gringo Suave Points 5985

La façon la plus évidente de le faire serait d'imprimer vers un objet fichier :

with open('out.txt', 'w') as f:
    print('Filename:', filename, file=f)  # Python 3.x
    print >> f, 'Filename:', filename     # Python 2.x

Cependant, la redirection de stdout fonctionne également pour moi. C'est probablement très bien pour un script ponctuel comme celui-ci :

import sys

orig_stdout = sys.stdout
f = open('out.txt', 'w')
sys.stdout = f

for i in range(2):
    print('i = ', i)

sys.stdout = orig_stdout
f.close()

Depuis Python 3.4, un gestionnaire de contexte simple est disponible pour effectuer cette opération. dans la bibliothèque standard :

from contextlib import redirect_stdout

with open('out.txt', 'w') as f:
    with redirect_stdout(f):
        print('data')

La redirection externe à partir du shell lui-même est une autre option, souvent préférable :

./script.py > out.txt

Autres questions :

Quel est le premier nom de fichier dans votre script ? Je ne le vois pas initialisé.

Ma première hypothèse est que glob ne trouve pas de bamfiles, et donc que la boucle for ne s'exécute pas. Vérifiez que le dossier existe, et imprimez les bamfiles dans votre script.

De même, utilisez os.path.join et os.path.basename pour manipuler les chemins et les noms de fichiers.

103voto

agf Points 45052

Vous pouvez rediriger l'impression avec l'option file (dans Python 2, il y avait l'argument >> à la place).

f = open(filename,'w')
print('whatever', file=f) # Python 3.x
print >>f, 'whatever'     # Python 2.x

Dans la plupart des cas, il est préférable d'écrire normalement dans le fichier.

f.write('whatever')

ou, si vous avez plusieurs éléments que vous voulez écrire avec des espaces entre eux, comme print :

f.write(' '.join(('whatever', str(var2), 'etc')))

61voto

Yeo Points 938

Python 2 o Python 3 Référence API :

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

El fichier doit être un objet avec un write(string) si elle n'est pas présente ou None , sys.stdout sera utilisé. Puisque les arguments imprimés sont convertis en chaînes de texte, print() ne peut pas être utilisé avec des objets fichiers en mode binaire. Pour ceux-ci, il faut utiliser file.write(...) à la place.

Depuis Objet du fichier contient normalement write() tout ce que vous devez faire est de passer un Objet du fichier dans son argumentation.

Ecriture/Surécriture dans un fichier

with open('file.txt', 'w') as f:
    print('hello world', file=f)

Écrire/Ajouter au fichier

with open('file.txt', 'a') as f:
    print('hello world', file=f)

46voto

jpyams Points 1122

N'utilisez pas print utiliser logging

Vous pouvez modifier sys.stdout pour pointer vers un fichier, mais il s'agit d'une manière assez maladroite et peu flexible de gérer ce problème. Au lieu d'utiliser print utilisez le logging module.

Avec logging vous pouvez imprimer comme vous le feriez pour stdout ou vous pouvez également écrire la sortie dans un fichier. Vous pouvez même utiliser les différents niveaux de message ( critical , error , warning , info , debug ) pour, par exemple, n'imprimer que les problèmes majeurs sur la console, mais continuer à enregistrer les actions de code mineures dans un fichier.

Un exemple simple

Importation logging obtenir le logger et définir le niveau de traitement :

import logging
logger = logging.getLogger()
logger.setLevel(logging.DEBUG) # process everything, even if everything isn't printed

Si vous voulez imprimer sur stdout :

ch = logging.StreamHandler()
ch.setLevel(logging.INFO) # or any other level
logger.addHandler(ch)

Si vous souhaitez également écrire dans un fichier (si vous souhaitez uniquement écrire dans un fichier, passez la dernière section) :

fh = logging.FileHandler('myLog.log')
fh.setLevel(logging.DEBUG) # or any level you want
logger.addHandler(fh)

Ensuite, partout où vous utiliserez print utiliser l'un des logger méthodes :

# print(foo)
logger.debug(foo)

# print('finishing processing')
logger.info('finishing processing')

# print('Something may be wrong')
logger.warning('Something may be wrong')

# print('Something is going really bad')
logger.error('Something is going really bad')

Pour en savoir plus sur l'utilisation d'outils plus avancés logging caractéristiques, lisez l'excellent logging tutoriel dans la documentation Python .

42voto

Pradeep Kumar Points 379

Cela fonctionne parfaitement :

import sys
sys.stdout=open("test.txt","w")
print ("hello")
sys.stdout.close()

Maintenant le bonjour sera écrit dans le fichier test.txt. Assurez-vous de fermer le fichier stdout avec un close sans lequel le contenu ne sera pas enregistré dans le fichier.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X