Tengo un script SGE para ejecutar algún código python, enviado a la cola usando qsub. En el script de Python, tengo algunas declaraciones impresas (actualizándome sobre el progreso del programa). Cuando ejecuto el script de python desde la línea de comando, las instrucciones de impresión se envían a stdout. Para el script sge, uso la opción -o para redirigir el resultado a un archivo. Sin embargo, parece que el script solo los enviará al archivo una vez que el script de python haya completado la ejecución. Esto es molesto porque (a) ya no puedo ver actualizaciones en tiempo real en el programa y (b) si mi trabajo no finaliza correctamente (por ejemplo, si mi trabajo es expulsado de la cola) no se imprime ninguna de las actualizaciones. ¿Cómo puedo asegurarme de que el script está escribiendo en el archivo cada vez que quiero imprimir algo, en lugar de agruparlo al final?SGE script: imprimir en el archivo durante la ejecución (no solo al final)?
Respuesta
Creo que se encuentra con un problema con la salida de búfer. Python usa una biblioteca para manejar su salida, y la biblioteca sabe que es más eficiente escribir un bloque a la vez cuando no está hablando con un tty.
Hay un par de formas de evitar esto. Puede ejecutar Python con la opción "-u" (consulte la página del pitón para más detalles), por ejemplo, con algo como esto como la primera línea del script:
#! /usr/bin/python -u
pero esto no funciona si está utilizando el truco "/ usr/bin/env" porque no sabe dónde está instalado Python.
Otra manera es volver a abrir la salida estándar con algo como esto:
import sys
import os
# reopen stdout file descriptor with write mode
# and 0 as the buffer size (unbuffered)
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
Nota el parámetro bufsize de os.fdopen se establece en 0 para forzarlo a estar sin búfer. Puedes hacer algo similar con sys.stderr.
Acabo de encontrar un problema similar con SGE, y no suggested method para "liberar" el archivo IO parecía funcionar para mí. Tuve que esperar hasta el final de la ejecución del programa para ver cualquier salida.
La solución alternativa que encontré fue envolver sys.stdout en un objeto personalizado que implementa de nuevo el método de "escritura". En lugar de escribir en stdout, este nuevo método abre el archivo donde se redirige IO, lo agrega con los datos deseados y luego cierra el archivo. Es un poco feo, pero encontré que resolvió el problema, ya que la apertura/cierre real del archivo obliga a IO a ser interactivo.
Aquí está un ejemplo mínimo:
import os, sys, time
class RedirIOStream:
def __init__(self, stream, REDIRPATH):
self.stream = stream
self.path = REDIRPATH
def write(self, data):
# instead of actually writing, just append to file directly!
myfile = open(self.path, 'a')
myfile.write(data)
myfile.close()
def __getattr__(self, attr):
return getattr(self.stream, attr)
if not sys.stdout.isatty():
# Detect redirected stdout and std error file locations!
# Warning: this will only work on LINUX machines
STDOUTPATH = os.readlink('/proc/%d/fd/1' % os.getpid())
STDERRPATH = os.readlink('/proc/%d/fd/2' % os.getpid())
sys.stdout=RedirIOStream(sys.stdout, STDOUTPATH)
sys.stderr=RedirIOStream(sys.stderr, STDERRPATH)
# Simple program to print msg every 3 seconds
def main():
tstart = time.time()
for x in xrange(10):
time.sleep(3)
MSG = ' %d/%d after %.0f sec' % (x, args.nMsg, time.time()-tstart)
print MSG
if __name__ == '__main__':
main()
Esto se SGE amortiguar la salida de su proceso, que sucede si es un proceso de pitón o cualquier otro.
En general, puede disminuir o desactivar el almacenamiento en memoria intermedia en SGE, cambiándolo y volviendo a compilar. Pero no es una gran cosa que hacer, todos esos datos se escribirán lentamente en el disco y afectarán su rendimiento general.
Esto funciona para mí:
class ForceIOStream:
def __init__(self, stream):
self.stream = stream
def write(self, data):
self.stream.write(data)
self.stream.flush()
if not self.stream.isatty():
os.fsync(self.stream.fileno())
def __getattr__(self, attr):
return getattr(self.stream, attr)
sys.stdout = ForceIOStream(sys.stdout)
sys.stderr = ForceIOStream(sys.stderr)
y la cuestión tiene que ver con NFS no sincronizar datos de nuevo al maestro hasta un archivo está cerrado o fsync se llama.
Como han mencionado otros, es por razones de rendimiento no escribir siempre la salida estándar cuando no está conectada a un tty.
Si usted tiene un punto específico en el que desea que la salida estándar a ser escrito, puede forzar a que mediante el uso
import sys
sys.stdout.flush()
en ese punto.
¿Por qué no imprimir en un archivo en lugar de stdout?
outFileID = open('output.log','w')
print(outFileID,'INFO: still working!')
print(outFileID,'WARNING: blah blah!')
y utilizar
tail -f output.log
llegué a este mismo problema hoy y lo resolvió con sólo escribir en el disco en lugar de imprimir:
with open('log-file.txt','w') as out:
out.write(status_report)
- 1. Cómo imprimir en la consola durante la ejecución del trabajo de MapReduce en hadoop
- 2. Script de Xcode Ejecución Fase de compilación "Ejecutar script solo al instalar" Opción
- 3. No repita TFOOT al imprimir
- 4. Escribiendo al final del archivo
- 5. TCL - ¿Cómo imprimir en la pantalla los mensajes que se imprimieron durante la ejecución del comando exec?
- 6. XmlIgnoreAttribute, solo se usa durante la serialización, ¿no durante la deserialización?
- 7. vinculando al servicio en ejecución (después del final())/callback Handler
- 8. cómo asegurarse de que un archivo se cerrará al final de la ejecución
- 9. C - ¿Por qué imprimir y no solo imprimir?
- 10. ¿Imprimir solo la última línea de un archivo?
- 11. ¿Cómo puedo mostrar algo durante la ejecución de un script SQL en SQLServer?
- 12. ejecución de script php en la consola
- 13. jQuery: la detección de llegar al final del desplazamiento no funciona, solo detecta la parte superior
- 14. configure log4j para iniciar sesión en el archivo personalizado durante el tiempo de ejecución
- 15. líneas de impresión en el archivo desde la línea de partido hasta el final del archivo
- 16. Cómo bloquear la orientación durante el tiempo de ejecución
- 17. Vim: cómo comenzar a insertar al final del archivo en un solo paso
- 18. Error durante el archivo
- 19. PrintWriter no se puede imprimir en el archivo
- 20. ¿Cómo imprimir el resultado del script de shell en CMake?
- 21. Cómo imprimir la siguiente matriz multidimensional en Java Script?
- 22. Problemas con la carga de recursos durante la ejecución
- 23. No se puede redirigir la salida cuando ejecuto el script de Python en Windows utilizando solo el nombre del script
- 24. Ejecutar la función solo en la primera ejecución ios
- 25. ¿Cómo elimino los corchetes al final de un nombre de variable JS durante las llamadas AJAX?
- 26. Servidor Sql imprimir filas afectadas durante el ciclo while
- 27. Cómo reparar la advertencia "No hay nueva línea al final del archivo" para muchos archivos?
- 28. Ejecuta dos comandos durante la ejecución de git bisect
- 29. jQuery Confirme el cuadro que detiene la ejecución del script
- 30. SGE - QSUB deja de enviar los trabajos en el modo -sync
Gracias! No me di cuenta de que esto tenía algo que ver con Python. También encontré este post útil http://stackoverflow.com/questions/107705/python-output-buffering – miz