rails portable learn instal create python ruby-on-rails ruby heroku rake

portable - ¿Cómo integrar una secuencia de comandos de Python independiente en una aplicación de Rails?



ruby on rails heroku (5)

Tengo un programa que tiene una pequeña estructura de archivos y luego se ejecuta usando

python do_work.py foo bar

Quiero que los usuarios de Rails presionen un botón y que esto suceda, y que el resultado se cargue en algún lugar o simplemente se les do_work.py como un enlace de descarga o algo por el estilo: el resultado de do_work.py (digamos, es result.txt )

También quiero aclarar que el script da como resultado la creación en el sistema de archivos de 3 archivos separados, que no son archivos de texto (lo que no debería importar y no es realmente el problema aquí)

¿Cuál es la mejor manera de hacerlo? ¿Puede rake ejecutar exec Python? Más importante aún, ¿es esto factible en heroku?

Tengo Python instalado en mi sistema, pero la respuesta provista por sockmonk no parece funcionar, devuelve nulo. Eso sí, otros comandos como ls parecen funcionar.

¿Podría ser un problema de permisos?

def index value = %x( python --version ) render :text => value end

Por cierto, probando esto en irb :

%x(python)

Trae el terminal de Python DENTRO de irb. Sin embargo, no tomará params por la razón que sea.


Depende de qué tan profundamente desee integrar el script de python. Hay formas de llamar realmente a los módulos de python directamente desde ruby.

http://www.goto.info.waseda.ac.jp/~fukusima/ruby/python-e.html

Esto le daría la ventaja de obtener el resultado directamente de su secuencia de comandos python en lugar de pasar por el dispositivo de E / S.


En parte depende del formato de los datos. Si no es demasiado largo y se puede representar directamente en el navegador, puede hacer algo como esto en un controlador de rieles:

result = `python do_work.py foo bar` render :text => result

Y suponiendo que el resultado sea texto ASCII simple, el resultado irá directamente a su navegador. Si los parámetros para do_work.py provienen del usuario, DEBES validarlos primero, para que no termines creando una desagradable vulnerabilidad para ti. Usar la llamada al sistema () probablemente sería más seguro en ese caso.

Si desea enviar los resultados nuevamente como un archivo, mire la clase Tempfile de ruby ​​para crear el archivo (de una manera que no se quede para siempre), y los comandos send_file y send_data de los rieles para algunas opciones diferentes para devolver los resultados de esa manera.


Haría algo como lo siguiente.

Ejecute asincrónicamente esta tarea en segundo plano. Y una vez que el resultado esté listo, denúncialo al usuario.

Una forma en que puede lograr esto será mediante el uso de Open3 y la gema delayed_job .

Eche un vistazo al método popen3 en el módulo Open3.

Open3.popen3([env,] cmd... [, opts]) {|stdin, stdout, stderr, wait_thr| pid = wait_thr.pid # pid of the started process. ... exit_status = wait_thr.value # Process::Status object returned. }

En su caso, puede cambiar la instrucción Open3.popen3 a algo como lo siguiente

Open3.popen3("python do_work.py foo bar"){ ... # mechanism for reporting like setting a flag in database system # or queue system }

Nota: debe dar la ruta completa a su secuencia de comandos python

Y luego usa la gema de retraso de trabajo para ejecutar esto como una tarea de fondo.

También debe tener un mecanismo de sondeo que sondeará el sistema para ver si el indicador está establecido, lo que significa que el resultado está listo y luego lo presentará al usuario.


La respuesta de utapyngo es cubrir casi todo lo que necesitas saber. Voy a responder esta parte:

por cierto, probando esto en irb:% x (python) Muestra el terminal de python DENTRO de irb. Sin embargo, no tomará params por la razón que sea.

Para pasar parámetros a su secuencia de comandos python, simplemente páselo. Ejemplo:

[fotanus@thing ~]$ python a.py args: [''a.py''] [fotanus@thing ~]$ irb 1.8.7 :001 > %x(python a.py foo bar) => "args:/n[''a.py'', ''foo'', ''bar'']/n"

Esto funciona en ruby ​​1.8, 1.9 y 2.0.


Su método de index no funciona porque python --version saca su versión a STDERR, no a STDOUT. Si no necesita separar estas secuencias, puede simplemente redirigir STDERR a STDOUT:

value = %x(python --version 2>&1)

Esta llamada es síncrona, por lo que después de ejecutar el script ( python do_work.py foo bar 2>&1 ), debería poder leer los archivos producidos por él.

Si el script no puede crear los archivos por alguna razón, ahora verá la excepción en la variable de value porque los mensajes de error generalmente se envían a STDERR.

Si desea separar STDERR de STDOUT, use el módulo Open3 .

Tenga en cuenta que el script tarda algo de tiempo en ejecutarse, por lo que las llamadas pueden superponerse. Usaría una cola aquí para evitar esto.

Y no olvide verificar los datos que ingresa el usuario. Nunca pasarlo directamente al script.