2010-06-03 25 views
7

Estoy tratando de crear una construcción en Python 3 que me permita ejecutar fácilmente una función en una máquina remota. Suponiendo que ya tengo un servidor TCP pitón que ejecutará las funciones que recibe, que se ejecuta en el servidor remoto, estoy buscando a utilizar un decorador como¿Cómo copio una función de python a una máquina remota y luego la ejecuto?

@execute_on(address, port) 

Esto crearía el contexto necesario requerido para ejecuta la función que está decorando y luego envía la función y el contexto al servidor tcp en la máquina remota, que luego la ejecuta. En primer lugar, ¿es esto algo sensato? Y si no, ¿podrías recomendar un mejor enfoque? He hecho algunas búsquedas en Google, pero no he encontrado nada que satisfaga estas necesidades.

Tengo una implementación rápida y sucia para el servidor tcp y el cliente, así que estoy bastante seguro de que funcionará. Puedo conseguir una representación de cadena de la función (por ejemplo func) ser pasado al decorador por

import inspect 
string = inspect.getsource(func) 

que luego puede ser enviada al servidor donde puede ser ejecutado. El problema es, ¿cómo obtengo toda la información de contexto que la función requiere para ejecutar? Por ejemplo, si se define de la siguiente manera func,

import MyModule 
def func(): 
    result = MyModule.my_func() 

MyModule tendrá que estar disponible para func ya sea en el contexto o funcs contexto local en el servidor remoto global. En este caso, es relativamente trivial, pero puede ser mucho más complicado dependiendo de cuándo y cómo se usan las declaraciones de importación. ¿Hay alguna manera fácil y elegante de hacer esto en Python? Lo mejor que he encontrado en este momento es usar la biblioteca ast para extraer todas las declaraciones de importación, utilizando el módulo de inspección para obtener representaciones de cadenas de esos módulos y luego reconstruir todo el contexto en el servidor remoto. No particularmente elegante y puedo ver mucho espacio para el error.

Gracias por su tiempo

Respuesta

0

¿Cuál es su objetivo final con esto? Según su descripción, no veo ninguna razón por la cual no pueda simplemente crear una clase de mensajería simple y enviar instancias de eso para ordenarle a la máquina remota que haga 'cosas' ...?

Hagas lo que hagas, tu máquina remota va a necesitar la fuente de Python para ejecutarse, entonces ¿por qué no distribuir el código allí y luego ejecutarlo? Podrías crear un servidor simple que aceptaría algunos archivos fuente de python, extraerlos importar los módulos relevantes y luego ejecutar un comando?

2

El enfoque que describe es extremadamente arriesgado a menos que el servidor remoto esté de alguna manera muy fuertemente protegido o "extremadamente aislado" (por ejemplo, una "cárcel" BSD). Cualquiera que pueda enviar funciones podría ejecutar código arbitrario allí .

Suponiendo que tiene un sistema de autenticación en el que confía por completo, surge el problema de "fragilidad" que se dio cuenta: la función puede depender de cualquier elemento global definido en su módulo en el momento de la ejecución (que puede ser diferente puede detectar por inspección: determinar el conjunto de módulos importados, y más generalmente de globales, en tiempo de ejecución, es un problema de Turing-completo).

Puede resolver el problema global serializando los valores globales de la función, así como la función en sí, al momento de enviarla para su ejecución remota (ya sea que serialice todo esto en forma de cadena legible, o de lo contrario, un problema menor). Pero eso todavía te deja con la cuestión de las importaciones realizadas dentro de la función.

A menos que usted está dispuesto a poner algunos limitaciones en la función "remoted", tales como "no hay importaciones dentro de la función (y las funciones llamadas de ella)", estoy pensando que podría tener el servidor de anulación __import__ (la función incorporada que es utilizada por todas las declaraciones de importación y está diseñada para ser anulada para necesidades peculiares, como la suya ;-) para solicitar el módulo adicional del cliente remitente (por supuesto, eso requiere que dicho cliente también tenga capacidades de "servidor", en el sentido de que debe ser capaz de responder a tales "solicitudes de módulos" desde el servidor).

¿No puede imponer algunas restricciones en las funciones que están remotas, para llevar esta tarea de nuevo al dominio de la cordura ...?

2

Puede interesarle el execnet project.

execnet proporciona medios cuidadosamente probados para interactuar fácilmente con los intérpretes de Python a través de la versión, plataforma y barreras de red. Tiene una API mínima y rápida que apuntan a los siguientes usos:

  • distribuir las tareas a las CPU local o remoto
  • escribir e implementar aplicaciones de múltiples procesos híbridos
  • secuencias de comandos de escritura para administrar un montón de entornos exec

http://codespeak.net/execnet/example/test_info.html#get-information-from-remote-ssh-account

he visto una demostración de ello. Pero nunca lo usé yo mismo.

+0

+1 para execnet. Lo he usado para ejecutar algunos casos de prueba de forma distribuida y funciona muy bien. –

0

Esto probablemente sea difícil de hacer y se encontrará con problemas de seguridad, argumentos, etc. Quizás pueda ejecutar un intérprete de Python de forma remota que pueda recibir código usando un socket o un servicio HTTP en lugar de hacerlo en una función por nivel de función?

1

No está claro por su pregunta si hay alguna limitación/requisito del sistema para que resuelva su problema de esta manera. De lo contrario, puede haber maneras mucho más fáciles y rápidas de hacerlo utilizando algún tipo de infraestructura de mensajería.

Por ejemplo, usted podría considerar si [Apio] [1]

[1]: http://ask.github.com/celery/getting-started/introduction.html satisfaga sus necesidades.

Cuestiones relacionadas