2010-11-04 5 views
5

Viniendo del mundo de Ruby, donde tenemos hermosos frameworks de máquinas de estado like the one recently baked into Rails, me ha sorprendido no encontrar un candidato obvio con una belleza similar en Python. Me gustaría evitar rodar el mío; Los diseños de máquinas de estado orientadas a objetos generalmente requieren que cuelgues un montón de pitones cada vez que agregas un estado (lo que haré a menudo, en este caso).¿Existe un hermoso framework de State Machine en Python?

¿Cuál es el marco para las máquinas de estado que debería utilizar en mi código de Python? Me gustaría el código más elegante, antes de cualquier actuación u otras consideraciones.

+3

"diseños orientados a objetos de máquinas de estado por lo general requieren que se honda un montón de pitón cada vez que añada un estado"? De Verdad? Todo lo que hice fue agregar una clase y modificar las diversas reglas de transición. El diseño ** Estandarte ** de pandillas funciona para mí. ¿Por qué no funciona para ti? ¿Tienes ejemplos? –

+1

Oh, funciona, funciona bien. No me importa hacerlo si el conjunto de estados es generalmente estable. En este caso, voy a terminar modificando la máquina de estados en básicamente todos los casos de prueba: escribir una nueva clase cada vez parece un poco complicado. –

+0

Además, definir la misma clase de "Estado" que todos los demás sienten repetitiva; Prefiero usar una clase estatal canónica, al menos. –

Respuesta

2

puede probar este fragmento

django acts_as_statemachine

+0

Oo, eso empieza a parecerse más. :) –

+0

Esto funciona maravillosamente, con una pequeña modificación para deshacerse de las dependencias de django. :) –

2

creo que la herramienta PySCXML necesita una mirada más cercana también. Este proyecto utiliza la definición del W3C: XML Tabla de Estado (SCXML): Estado Anotación de máquina para la abstracción de control

SCXML proporciona un entorno de ejecución basado en el estado de la máquina genérico basado en CCXML y estatales Harel Tablas

Actualmente, SCXML es una borrador de trabajo; pero hay muchas posibilidades de que reciba una recomendación del W3C pronto (es el noveno borrador).

Otro punto interesante a destacar es que hay un proyecto de Apache Commons destinado a crear y mantener un motor SCXML Java capaz de ejecutar una máquina de estados definida utilizando un documento SCXML, mientras abstrae las interfaces de entorno ... Y para ciertos otras herramientas que admitan esta tecnología surgirán en el futuro cuando SCXML deje su estado de borrador ...

1

A menudo solo uso un dict para la descripción de la máquina de estado. Dependiendo de la aplicación, las claves podrían ser (estado, evento), los valores podrían ser (new_state, args). Por ejemplo:

machine = { 
     ('state_a', 'x'): ('state_b', 'arg1'), 
     ('state_b', 'y'): ('state_c', 'arg2'), 
     ... 
} 

La clase, función o generador de leer y ejecutar ese dict puede ser bastante simple, dependiendo de cómo desea que sus transiciones hacia el trabajo. Un generador que utilice el método .send() más reciente de python podría ser una forma de escribir un componente simple Model-View-Controller impulsado por eventos, por ejemplo. El uso de devoluciones de llamadas en lugar de cadenas para estados y/o eventos eliminará la necesidad de una gran cantidad de código si/entonces también.

Sé que esto es "renovar el suyo", pero en la práctica he descubierto que todo esto cabe en un par de docenas de líneas de código, dependiendo del tamaño de la máquina de estado, y se puede adaptar para adaptarse a la aplicación mejor que el marco genérico típico. A menudo requiere menos código de configuración que esos marcos también.

Aquí hay un ejemplo un poco más completo, utilizando devoluciones de llamada para el estado: este es el tipo de cosas que haría si siempre desea ejecutar el mismo código en la entrada de estado. (El uso de devoluciones de llamada de eventos le daría código específico para la transición en su lugar.):

def foo(x): 
    print 'foo got', x 
    return 'x' 

def bar(x): 
    print 'bar got', x 
    return 'y' 

def baz(x): 
    print 'baz got', x 
    return 'z' 

machine = { 
    (foo, 'x'): (bar, 'arg1'), 
    (bar, 'y'): (baz, 'arg2'), 
    (baz, 'z'): (foo, 'arg3'), 
    } 

state,arg = foo,'arg0' 
while True: 
    event = state(arg) 
    res = machine.get((state, event)) 
    if not res: 
     print "halting on", state, event 
     break 
    state,arg = res 

Aquí está la salida:

foo got arg0 
bar got arg1 
baz got arg2 
foo got arg3 
bar got arg1 
baz got arg2 
foo got arg3 
bar got arg1 
baz got arg2 
foo got arg3 
... 
1

Sé que es un poco tarde, pero se acaba de hacer algunas investigaciones y descubrió este enviar. He escrito mi propio Statemachine incluido en mi proyecto django-ostinato.

https://github.com/andrewebdev/django-ostinato/blob/master/ostinato/statemachine/core.py

Documentación aquí: https://django-ostinato.readthedocs.org/en/latest/ostinato.statemachine.html

El StateMachine está escrito de manera que no tiene que ser integrado en un modelo Django directamente en absoluto, pero por lo que se puede inicializar utilizando un modelo ejemplo. Lo he estado usando para un par de worfklows de statemachine complejos.

Además, statemachine es independiente del marco, porque solo está pasando una instancia de objeto. Solo necesita asegurarse de que la instancia tenga una propiedad que contenga el estado real.

Probablemente haya enfoques mucho mejores por ahí, pero esto me ha servido hasta ahora.

2

Estoy buscando lo mismo, de momento xworkflow parece el mejor candidato que puedo encontrar.

Aunque soy muy nuevo en Python, me parece que no hay bibliotecas estándar para todo, pero hay un montón de implementaciones independientes disponibles por la comunidad, algunas son más pitónicas que otras, pero en el La mayoría de ellos son geniales. Otras implementaciones que encontré se enumeran a continuación.

Cuestiones relacionadas