Je souhaite rediriger l'impression vers un fichier .txt en utilisant python. J'ai une boucle «for», qui «imprimera» la sortie pour chacun de mes fichiers .bam pendant que je souhaite rediriger TOUTES ces sorties vers un fichier. Alors j'ai essayé de mettre
f = open('output.txt','w'); sys.stdout = f
au début de mon scénario. 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!'
........print....
........print....
Donc quel est le problème? Un autre moyen en plus de ce sys.stdout?
J'ai besoin que mon résultat ressemble à:
Filename: ERR001268.bam
Readlines finished!
Mean: 233
SD: 10
Interval is: (213, 252)
================= Comment le temps passe vite. Il y a près de 10 ans, j'ai commencé à travailler sur la bioinformatique sans aucune compétence en codage. Ensuite, j'ai abandonné mon doctorat et ma carrière précédente et suis devenu un pur ingénieur logiciel.
python
file-writing
LookIntoEast
la source
la source
f.write(data)
?f.write(line)
- il insère un saut de ligne à la fin.f.write(line)
n'ajoute pas de saut de ligne aux données.f.write(line+'\n')
, cependant ..Réponses:
La manière la plus évidente de le faire serait d'imprimer dans un objet fichier:
with open('out.txt', 'w') as f: print >> f, 'Filename:', filename # Python 2.x print('Filename:', filename, file=f) # Python 3.x
Cependant, la redirection stdout fonctionne également pour moi. C'est probablement bien pour un script unique 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()
La redirection externe à partir du shell lui-même est une autre bonne option:
D'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 aucun fichier bam et que la boucle for ne s'exécute donc pas. Vérifiez que le dossier existe et imprimez les bamfiles dans votre script.
Utilisez également os.path.join et os.path.basename pour manipuler les chemins et les noms de fichiers.
la source
Vous pouvez rediriger l'impression avec l'
>>
opérateur.f = open(filename,'w') print >>f, 'whatever' # Python 2.x print('whatever', file=f) # Python 3.x
Dans la plupart des cas, il vaut mieux simplement écrire normalement dans le fichier.
f.write('whatever')
ou, si vous souhaitez écrire plusieurs éléments avec des espaces, comme
print
:f.write(' '.join(('whatever', str(var2), 'etc')))
la source
sys.stdout
, non pas que c'était une bonne idée.Étant donné que l'objet fichier contient normalement une
write()
méthode, tout ce que vous avez à faire est de passer un objet fichier dans son argument.Ecrire / écraser 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)
la source
sys.stdout
:(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
stdout
avec unclose
, sans lui, le contenu ne sera pas enregistré dans le fichierla source
sys.stdout.close()
, si vous tapez quelque chose dans le shell python, l'erreur seraValueError: I/O operation on closed file.
affichée sous la forme imgur.com/a/xby9P . La meilleure façon de gérer cela est de suivre ce que @Gringo Suave a publiéNe pas utiliser
print
, utiliserlogging
Vous pouvez changer
sys.stdout
pour pointer vers un fichier, mais c'est une manière assez maladroite et inflexible de gérer ce problème. Au lieu d'utiliserprint
, utilisez lelogging
module.Avec
logging
, vous pouvez imprimer comme vous le feriezstdout
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
), par exemple, n'imprimer les grandes questions à la console, mais toujours enregistrer les actions mineures du code dans un fichier.Un exemple simple
Importez
logging
, récupérezlogger
et définissez le niveau de traitement:import logging logger = logging.getLogger() logger.setLevel(logging.DEBUG) # process everything, even if everything isn't printed
Si vous souhaitez 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 ne souhaitez écrire que 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, où que vous utilisiez,
print
utilisez l'une deslogger
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 de fonctionnalités plus avancées
logging
, lisez l'excellentlogging
didacticiel de la documentation Python .la source
La solution la plus simple n'est pas via python; c'est à travers la coque. Depuis la première ligne de votre fichier (
#!/usr/bin/python
), je suppose que vous êtes sur un système UNIX. Utilisez simplement desprint
instructions comme vous le feriez normalement, et n'ouvrez pas du tout le fichier dans votre script. Lorsque vous exécutez le fichier, au lieu depour exécuter le fichier, utilisez
où vous remplacez
<filename>
par le nom du fichier dans lequel vous voulez que la sortie entre. Le>
jeton dit (à la plupart) des shells de définir stdout sur le fichier décrit par le jeton suivant.Une chose importante qui doit être mentionnée ici est que "script.py" doit être rendu exécutable pour
./script.py
fonctionner.Alors avant de courir
./script.py
, exécutez cette commandechmod a+x script.py
(rendre le script exécutable pour tous les utilisateurs)la source
print
vers un fichier. Il serait raisonnable de s'attendre à ce que stdout (traces de pile et autres) s'imprime toujours sur le terminal.Si vous utilisez Linux, je vous suggère d'utiliser la
tee
commande. La mise en œuvre va comme ceci:Si vous ne voulez rien changer dans le code, je pense que c'est peut-être la meilleure solution possible. Vous pouvez également implémenter un enregistreur, mais vous devez apporter des modifications au code.
la source
Vous n'aimerez peut-être pas cette réponse, mais je pense que c'est la BONNE. Ne changez pas votre destination stdout sauf si c'est absolument nécessaire (peut-être que vous utilisez une bibliothèque qui ne sort que vers stdout ??? clairement pas le cas ici).
Je pense que comme une bonne habitude, vous devez préparer vos données à l'avance sous forme de chaîne, puis ouvrez votre fichier et écrivez le tout en même temps. En effet, les opérations d'entrée / sortie sont plus longues que vous avez un descripteur de fichier ouvert, plus une erreur est susceptible de se produire avec ce fichier (erreur de verrouillage de fichier, erreur d'E / S, etc.). Faire tout cela en une seule opération ne laisse aucune question quant au moment où cela aurait pu mal tourner.
Voici un exemple:
out_lines = [] for bamfile in bamfiles: filename = bamfile.split('/')[-1] out_lines.append('Filename: %s' % filename) samtoolsin = subprocess.Popen(["/share/bin/samtools/samtools","view",bamfile], stdout=subprocess.PIPE,bufsize=1) linelist= samtoolsin.stdout.readlines() print 'Readlines finished!' out_lines.extend(linelist) out_lines.append('\n')
Et puis lorsque vous avez fini de collecter vos "lignes de données" une ligne par élément de liste, vous pouvez les joindre avec quelques
'\n'
caractères pour créer une table de sortie; peut-être même envelopper votre instruction de sortie dans unwith
bloc, pour plus de sécurité (fermera automatiquement votre poignée de sortie même si quelque chose ne va pas):out_string = '\n'.join(out_lines) out_filename = 'myfile.txt' with open(out_filename, 'w') as outf: outf.write(out_string) print "YAY MY STDOUT IS UNTAINTED!!!"
Cependant, si vous avez beaucoup de données à écrire, vous pouvez les écrire un morceau à la fois. Je ne pense pas que ce soit pertinent pour votre application, mais voici l'alternative:
out_filename = 'myfile.txt' outf = open(out_filename, 'w') for bamfile in bamfiles: filename = bamfile.split('/')[-1] outf.write('Filename: %s' % filename) samtoolsin = subprocess.Popen(["/share/bin/samtools/samtools","view",bamfile], stdout=subprocess.PIPE,bufsize=1) mydata = samtoolsin.stdout.read() outf.write(mydata) outf.close()
la source
Si la redirection
stdout
fonctionne pour votre problème, la réponse de Gringo Suave est une bonne démonstration pour savoir comment le faire.Pour rendre les choses encore plus faciles , j'ai créé une version utilisant des contextmanagers pour une syntaxe d'appel généralisée succincte en utilisant l'
with
instruction:from contextlib import contextmanager import sys @contextmanager def redirected_stdout(outstream): orig_stdout = sys.stdout try: sys.stdout = outstream yield finally: sys.stdout = orig_stdout
Pour l'utiliser, il suffit de faire ce qui suit (dérivé de l'exemple de Suave):
with open('out.txt', 'w') as outfile: with redirected_stdout(outfile): for i in range(2): print('i =', i)
C'est utile pour rediriger sélectivement
print
lorsqu'un module l'utilise d'une manière que vous n'aimez pas. Le seul inconvénient (et c'est le dealbreaker dans de nombreuses situations) est que cela ne fonctionne pas si l'on veut plusieurs threads avec des valeurs différentes destdout
, mais cela nécessite une meilleure méthode plus généralisée: l'accès indirect aux modules. Vous pouvez voir des implémentations de cela dans d'autres réponses à cette question.la source
La modification de la valeur de sys.stdout change la destination de tous les appels à imprimer. Si vous utilisez une autre manière de changer la destination de l'impression, vous obtiendrez le même résultat.
Votre bug est ailleurs:
la source
Quelque chose pour étendre la fonction d'impression pour les boucles
x = 0 while x <=5: x = x + 1 with open('outputEis.txt', 'a') as f: print(x, file=f) f.close()
la source
while
et pas besoin de fermer le fichier lors de l'utilisationwith