2010-01-20 16 views
7

Escribí una secuencia de comandos python para procesar algunos datos de archivos CSV. El script tarda entre 3 y 30 minutos en completarse, dependiendo del tamaño del CSV.Creación de una interfaz web para una secuencia de comandos que tarda 30 minutos en ejecutarse

Ahora quiero poner una interfaz web para esto, así puedo cargar los archivos de datos CSV desde cualquier lugar. Escribí una página de carga HTTP POST básica y utilicé el módulo CGI de Python, pero el script simplemente se agota después de un tiempo.

La secuencia de comandos emite encabezados HTTP al inicio y genera bits de datos después de iterar sobre cada línea de la CSV. Como ejemplo, esta declaración de impresión se activaría cada 30 segundos más o menos.

# at the very top, with the 'import's 
print "Content-type: text/html\n\n Processing ... <br />" 

# the really long loop. 
for currentRecord in csvRecords: 
    count = count + 1 
    print "On line " + str(count) + " <br />" 

Supuse que el navegador recibiría los encabezados, y espere porque sigue recibiendo pequeños bits de datos. Pero lo que realmente parece suceder es que no recibe ningún dato, y Error 504 agota el tiempo cuando se le entrega un CSV con muchas líneas.

¿Quizás hay algo de almacenamiento en caché en algún lugar? A partir de los registros,

[Wed Jan 20 16:59:09 2010] [error] [client ::1] Script timed out before returning headers: datacruncher.py, referer: http://localhost/index.htm 
[Wed Jan 20 17:04:09 2010] [warn] [client ::1] Timeout waiting for output from CGI script /Library/WebServer/CGI-Executables/datacruncher.py, referer: http://localhost/index.htm 

¿Cuál es la mejor manera de resolver esto, o, no es apropiado para ejecutar este tipo de scripts en un navegador?

Editar: Este es un script para mi propio uso - que normalmente la intención de usarlo en mi equipo, pero me pareció una interfaz basada en la web podría ser útil durante el viaje, o por ejemplo, de un teléfono. Además, realmente no hay nada que descargar: el script probablemente enviará por correo electrónico un informe al final.

+3

¿Cree que alguien en esta tierra tiene paciencia suficiente para esperar 30 minutos para cargar una página web en el navegador, en lugar de descargarla como datos? – YOU

+0

Este es un script para mi propio uso. Normalmente tengo la intención de usarlo en mi computadora, pero pensé que una interfaz basada en web podría ser útil mientras viaja, o por ejemplo desde un teléfono. Además, no hay nada que descargar: el script enviará un informe por correo electrónico al final. – Pranab

+0

@Pranab: "Este es un script para mi propio uso". Entonces, ¿qué problema tienes? ¿Por qué no dejarlo correr? ¿Por qué perder el tiempo? Si es para usted, y solo envía un correo electrónico, ni siquiera es una página web, ¿verdad? ¿Por qué no simplemente escribir un simple script de Python? –

Respuesta

12

que separaría el trabajo de esta manera:

  1. Un URL de la aplicación web que aceptan el archivo CSV publicado. La aplicación web coloca el contenido CSV en una cola fuera de línea, por ejemplo, una tabla de base de datos. La respuesta de la aplicación web debe ser una identificación única para el elemento en cola (por ejemplo, use una columna de identificación con incremento automático). El cliente debe almacenar esta identificación para la parte 3.

  2. Una aplicación de servicio independiente que sondea la cola para el trabajo y realiza el procesamiento. Una vez completado el procesamiento, almacene los resultados en otra tabla de base de datos, utilizando la ID única como clave.

  3. URL de una aplicación web que puede obtener resultados procesados, http://server/getresults/uniqueid/. Si el procesamiento ha finalizado (es decir, el ID único se encuentra en la tabla de la base de datos de resultados), devuelva los resultados. Si no se completa, la respuesta debe ser un código que lo indique. Por ejemplo, un encabezado HTTP personalizado, una respuesta de estado HTTP, un cuerpo de respuesta 'PENDIENTE' o similar.

5

He tenido esta situación antes y he usado cronjobs. El script HTTP simplemente escribiría en una cola un trabajo para realizar (un DB o un archivo en un directorio) y el cronjob lo leería y ejecutaría ese trabajo.

+0

+1; el usuario podría ser notificado por correo electrónico cuando finalice su trabajo, con un enlace para descargarlo –

+0

También puede hacer que el cronjob escriba su progreso periódicamente en un archivo y use ajax para leer el valor del servidor web y mostrarlo al usuario en su navegador . – sharjeel

+0

Si necesita que el proceso de trabajo se ejecute como un usuario diferente, usar un cronjob es una buena manera. De lo contrario, por lo general es igual de fácil iniciar el proceso de subprocesos directamente desde la aplicación CGI. – Wim

1

imho la mejor manera sería ejecutar un script independiente que publique actualizaciones en algún lugar (archivo plano, base de datos, etc.). No sé cómo bifurcar un proceso independiente de python, así que no puedo dar ningún ejemplo de código.

Para mostrar el progreso en un sitio web, implemente una solicitud ajax a una página que lea esas actualizaciones de estado y, por ejemplo, muestre una bonita barra de progreso.

añadir algo como setTimeout ("refreshProgressBar [...]) o meta-actualización para la actualización automática.

4

Es probable que tenga que hacer un stdout.flush(), ya que el guión no está realmente escrito nada todavía al servidor web hasta que haya escrito los datos del buffer de una página, lo que no ocurre antes del tiempo de espera.

Pero la forma correcta de resolver esto es, como otros sugirieron, hacer el procesamiento en un hilo separado/proceso, y mostrar al usuario una página actualizada automáticamente que muestra el estado, con una barra de progreso u otra visual elegante para evitar que se aburran.

+0

Agregar sys.stdout.flush() justo después de una declaración de impresión en el bucle parece resolver el problema. – Pranab

2

Pregunta muy similar here. Sugiero desviar el largo proceso y devolver una barra de progreso basada en ajax al usuario. De esta manera, el usuario tiene el lujo de la interfaz web y puede darse el lujo de no tener tiempos de espera excedidos.

Cuestiones relacionadas