read - python write text file
¿Cómo redirigir la salida de ''impresión'' a un archivo usando Python? (10)
Quiero redirigir la impresión a un archivo .txt usando Python. Tengo un bucle ''for'', que ''imprimirá'' la salida para cada uno de mis archivos .bam mientras quiero redirigir TODOS estos resultados a un archivo. Así que traté de poner
f = open(''output.txt'',''w''); sys.stdout = f
al comienzo de mi script Sin embargo, no obtengo nada en el archivo .txt. Mi guion es:
#!/usr/bin/python
import os,sys
import subprocess
import glob
from os import path
f = open(''output.txt'',''w'')
sys.stdout = f
path= ''/home/xug/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....
¿Entonces, cuál es el problema? De otra manera además de este sys.stdout?
Necesito que mi resultado se vea así:
Filename: ERR001268.bam
Readlines finished!
Mean: 233
SD: 10
Interval is: (213, 252)
Referencia de Python 2 o Python 3 API:
print(*objects, sep='' '', end=''/n'', file=sys.stdout, flush=False)
El argumento del archivo debe ser un objeto con un método de
write(string)
; si no está presente oNone
, sesys.stdout
. Como los argumentos impresos se convierten a cadenas de texto,print()
no se puede usar con objetos de archivos de modo binario. Para estos, usefile.write(...)
lugar.
Dado que el objeto de archivo normalmente contiene el método de write()
, todo lo que necesita hacer es pasar un objeto de archivo a su argumento.
Escribir / sobrescribir para archivar
with open(''file.txt'', ''w'') as f:
print(''hello world'', file=f)
Escribir / Anexar al archivo
with open(''file.txt'', ''a'') as f:
print(''hello world'', file=f)
No use print
, use el logging
Puede cambiar sys.stdout
para apuntar a un archivo, pero esta es una forma bastante torpe e inflexible de manejar este problema. En lugar de usar la print
, use el módulo de logging
.
Con el logging
, puede imprimir como lo haría en stdout
, o también puede escribir el resultado en un archivo. Incluso puede usar los diferentes niveles de mensajes ( critical
, error
, warning
, info
, debug
) para, por ejemplo, imprimir problemas importantes en la consola, pero aun así registrar acciones de código menores en un archivo.
Un simple ejemplo
Importar el logging
, obtener el logger
y establecer el nivel de procesamiento:
import logging
logger = logging.getLogger()
logger.setLevel(logging.DEBUG) # process everything, even if everything isn''t printed
Si desea imprimir en stdout:
ch = logging.StreamHandler()
ch.setLevel(logging.INFO) # or any other level
logger.addHandler(ch)
Si también desea escribir en un archivo (si solo desea escribir en un archivo, omita la última sección):
fh = logging.FileHandler(''myLog.log'')
fh.setLevel(logging.DEBUG) # or any level you want
logger.addHandler(fh)
Luego, donde quiera que use la print
use uno de los métodos de logger
:
# 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'')
Para obtener más información sobre el uso de funciones de logging
más avanzadas, lea el excelente tutorial de logging
en los documentos de Python .
Algo para extender la función de impresión para bucles
x = 0
while x <=5:
x = x + 1
with open(''outputEis.txt'', ''a'') as f:
print(x, file=f)
f.close()
Cambiar el valor de sys.stdout cambia el destino de todas las llamadas para imprimir. Si usa una forma alternativa de cambiar el destino de la impresión, obtendrá el mismo resultado.
Tu error está en otro lugar:
- podría estar en el código que eliminó para su pregunta (¿de dónde viene el nombre del archivo para que se abra la llamada?)
- también podría ser que no espere a que se vacíen los datos: si imprime en un terminal, los datos se vacían después de cada nueva línea, pero si imprime en un archivo, solo se vacía cuando el búfer stdout está lleno (4096 bytes) en la mayoría de los sistemas).
Esto funciona perfectamente:
import sys
sys.stdout=open("test.txt","w")
print ("hello")
sys.stdout.close()
Ahora el saludo se escribirá en el archivo test.txt. Asegúrese de cerrar el stdout
con un close
, sin él, el contenido no se guardará en el archivo
La forma más obvia de hacer esto sería imprimir en un objeto de archivo:
with open(''out.txt'', ''w'') as f:
print >> f, ''Filename:'', filename # Python 2.x
print(''Filename:'', filename, file=f) # Python 3.x
Sin embargo, redirigir stdout también funciona para mí. Probablemente esté bien para un script único como este:
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()
¿Cuál es el primer nombre de archivo en tu script? No lo veo inicializado.
Mi primera suposición es que glob no encuentra bamfiles y, por lo tanto, el bucle for no se ejecuta. Verifique que la carpeta exista e imprima bamfiles en su script.
Además, use os.path.join y os.path.basename para manipular rutas de acceso y nombres de archivos.
La solución más fácil no es a través de python; es a través del caparazón. Desde la primera línea de tu archivo ( #!/usr/bin/python
) supongo que estás en un sistema UNIX. Simplemente use print
declaraciones print
como lo haría normalmente, y no abra el archivo en absoluto en su secuencia de comandos. Cuando vas a ejecutar el archivo, en lugar de
./script.py
para ejecutar el archivo, use
./script.py > <filename>
donde reemplaza <filename>
con el nombre del archivo al que desea que vaya la salida. El símbolo >
indica (la mayoría) de las shells para establecer stdout en el archivo descrito por el siguiente token.
Una cosa importante que debe mencionarse aquí es que "script.py" debe ser ejecutable para que se ejecute ./script.py
.
Entonces, antes de ejecutar ./script.py
, ejecuta este comando
chmod a+x script.py
(hacer que el script sea ejecutable para todos los usuarios)
Puede que no te guste esta respuesta, pero creo que es la correcta. No cambie su destino estándar a menos que sea absolutamente necesario (tal vez esté usando una biblioteca que solo muestra "stdout" claramente no es el caso aquí).
Creo que es un buen hábito que debe preparar sus datos con anticipación como una cadena, luego abra su archivo y escriba todo al mismo tiempo. Esto es porque las operaciones de entrada / salida son mientras más tiempo tenga abierto un manejador de archivo, más probable es que ocurra un error con este archivo (error de bloqueo de archivo, error de E / S, etc.). Simplemente hacerlo todo en una sola operación no deja dudas sobre cuándo podría haber salido mal.
Aquí hay un ejemplo:
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'')
Y luego, cuando haya terminado de recopilar sus "líneas de datos" una línea por elemento de la lista, puede unirlas con algunos caracteres ''/n''
para hacer que todo sea reproducible; tal vez incluso envuelva su declaración de salida en un bloque with
, para mayor seguridad (cerrará automáticamente su identificador de salida incluso si algo sale mal):
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!!!"
Sin embargo, si tiene muchos datos para escribir, puede escribirlos de a una por vez. No creo que sea relevante para su aplicación, pero esta es la alternativa:
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()
Puede redirigir la impresión con el operador >>
.
f = open(filename,''w'')
print >>f, ''whatever'' # Python 2.x
print(''whatever'', file=f) # Python 3.x
En la mayoría de los casos, es mejor que solo escriba en el archivo normalmente.
f.write(''whatever'')
o, si tiene varios elementos que desea escribir con espacios entre ellos, como print
:
f.write('' ''.join((''whatever'', str(var2), ''etc'')))
Si usas linux, te sugiero que uses el comando tee
la implementación es como este python python_file.py |tee any_file_name.txt
si no quieres cambiar nada en el código, creo que esta podría ser la mejor solución posible, también puedes implementar registrador pero necesita hacer algunos cambios en el código.