Paralelo mientras bucles en Python

Soy bastante nuevo en Python, y en la progtwigción en general, y estoy creando un juego de mascotas virtual para mi hermana pequeña.

¿Es posible ejecutar 2 mientras que los bucles son paralelos entre sí en python? p.ej:

while 1: input_event_1 = gui.buttonbox( msg = 'Hello, what would you like to do with your Potato Head?', title = 'Main Screen', choices = ('Check Stats', 'Feed', 'Exercise', 'Teach', 'Play', 'Go to Doctor', 'Sleep', 'Change Favourite Thing', 'Get New Toy', 'Quit')) if input_event_1 == 'Check Stats': myPotatoHead.check_p_h_stats() elif input_event_1 == 'Feed': myPotatoHead.feed_potato_head() elif input_event_1 == 'Exercise': myPotatoHead.exercise_potato_head() elif input_event_1 == 'Teach': myPotatoHead.teach_potato_head(myPotatoHead) elif input_event_1 == 'Play': myPotatoHead.play_with_toy() elif input_event_1 == 'Sleep': myPotatoHead.put_p_h_asleep() elif input_event_1 == 'Go to Doctor': myPotatoHead.doctor_check_up() elif input_event_1 == 'Change Favourite Thing': myPotatoHead.change_favourite_thing() elif input_event_1 == 'Quit': input_quit = gui.ynbox( msg = 'Are you sure you want to quit?', title = 'Confirm quit', choices = ('Quit', 'Cancel')) if input_quit == 1: sys.exit(0) while 1: time.sleep(20) myPotatoHead.hunger = str(float(myPotatoHead.hunger) + 1.0) myPotatoHead.happiness = str(float(myPotatoHead.happiness) - 1.0) myPotatoHead.tiredness = str(float(myPotatoHead.tiredness) + 1.0) 

Si no, ¿hay alguna manera de que pueda convertir esto en un solo bucle? Quiero que las cosas en el segundo bucle sucedan cada 20 segundos, pero las cosas en el primer bucle ocurren constantemente.

Gracias por cualquier ayuda

Echar un vistazo a Threading.Timer .

Aquí hay una receta de código para progtwigr una función para que se ejecute cada 5 segundos .

 import thread import threading class Operation(threading._Timer): def __init__(self, *args, **kwargs): threading._Timer.__init__(self, *args, **kwargs) self.setDaemon(True) def run(self): while True: self.finished.clear() self.finished.wait(self.interval) if not self.finished.isSet(): self.function(*self.args, **self.kwargs) else: return self.finished.set() class Manager(object): ops = [] def add_operation(self, operation, interval, args=[], kwargs={}): op = Operation(interval, operation, args, kwargs) self.ops.append(op) thread.start_new_thread(op.run, ()) def stop(self): for op in self.ops: op.cancel() self._event.set() if __name__ == '__main__': # Print "Hello World!" every 5 seconds import time def hello(): print "Hello World!" timer = Manager() timer.add_operation(hello, 5) while True: time.sleep(.1) 

La única forma de “tener dos bucles while en paralelo” sería colocarlos en subprocesos diferentes, pero luego deberá abordar los problemas de sincronización y coordinación entre ellos, ya que están llegando al mismo objeto.

Le sugiero que en su lugar ponga un control de tiempo en el primer ciclo (y único) y realice los aumentos que ahora tiene en el segundo ciclo de manera proporcional a ese control de tiempo; no del todo satisfactoria, ya que la llamada de la buttonbox puede tardar un tiempo indefinido en regresar, pero es mucho más fácil de organizar, especialmente. Para un principiante, que la coordinación adecuada de hilos.

Una vez que tenga la lógica básica en su lugar y funcionando, entonces puede considerar los hilos nuevamente (con un temporizador periódico para lo que le gustaría en el segundo bucle en un hilo, la llamada del botón de locking en el hilo principal [[Creo que en easygui tiene que ser]], ambos eventos de alimentación en una Cola.Queue [[intrínsecamente seguro para subprocesos]] con otro subproceso obteniéndolos y operando en consecuencia, es decir, la mayoría de lo que ahora tiene en el primer ciclo). Pero ese es un problema arquitectónico bastante avanzado, por lo que te recomiendo que no trates de lidiar con él ahora mismo.

Debería usar State Machines para esto (vea el libro de Apress pygame – descargas aquí: http://apress.com/book/downloadfile/3765 ), vea el capítulo 7.

Una máquina de estados simplificada:

 def do_play(pet, time_passed): pet.happiness += time_pass*4.0 def do_feed(pet, time_passed): pet.hunger -= time_passed*4.0 def do_sleep(pet, time_passed): pet.tiredness += time_passed*4.0 if pet.tiredness <= 0: return 'Waiting' def do_waiting(pet, time_passed): pass def do_howl(pet, time_passed): print 'Hoooowl' def do_beg(pet, time_passed): print "I'm bored!" def do_dead(pet, time_passed): print '...' STATE_TO_FUNC = dict(Waiting=do_waiting, Sleeping=do_sleep, Feeding=do_feed, Playing=do_play, Howling=do_howl, Begging=do_beg, Dead=do_dead ) class Pet: def __init__(self): self.state = 'Waiting' self.hunger = 1.0 self.tiredness = 1.0 self.happiness = 1.0 def process(self, time_passed): self.hunger +=1*time_passed self.tiredness +=1*time_passed self.happiness -= 1*time_passed func = STATE_TO_FUNC[self.state] new_state = func(self, time_passed) if new_state is not None: self.set_state(new_state) if self.hunger >10: self.set_state('Dead') elif self.hunger > 5 and not (self.state == 'Feeding'): self.set_state('Howling') elif self.tiredness > 5: self.set_state('Sleeping') elif self.happiness < 0 and not (self.state == 'Playing'): self.set_state('Begging') def set_state(self,state): if not self.state == 'Dead': self.state = state from msvcrt import getch import time pet = Pet() while True: time0 = time.time() cmd = getch() # what command? pet.process(time.time()-time0) if cmd == 'a': pet.set_state('Feeding') if cmd == 's': pet.set_state('Sleeping') if cmd == 'd': pet.set_state('Playing') 

poner uno de ellos en una función, la clase threading.Thread admite un atributo de destino:

 import threading threading.Thread(target=yourFunc).start() 

Se iniciará yourFunc () ejecutándose en segundo plano.

Esencialmente para que el procesamiento tenga lugar en paralelo tienes varias soluciones.

1- Procesos separados (es decir, progtwigs) que se ejecutan de forma independiente y se comunican entre sí mediante un protocolo específico (por ejemplo: Sockets)

2- O puedes hacer que el proceso se genere en múltiples hilos.

3- Construir una cola de eventos internamente y procesarlos uno por uno

Ese es el cuadro general.

En cuanto a la respuesta específica a tu pregunta, dijiste “las cosas en el primer ciclo para que b [e] sucedan constantemente”. La realidad es que nunca quieres que esto suceda todo el tiempo, ya que todo lo que harás es utilizar el 100% de la CPU y nada más se hará.

La solución más sencilla es probablemente la número 3.

La forma en que lo implementaría es en mi bucle principal un hilo que pasa por una cola de eventos y establece un temporizador para cada evento. Una vez que se han enviado todos los temporizadores, el bucle principal se pone en suspensión.

Cuando un temporizador se agota, otra función ejecutará la función correspondiente para el evento que activó ese temporizador.

En tu caso, tienes dos eventos. Uno para mostrar el menú de selección (primer bucle) y el segundo para cambiar myPotatoHead. El temporizador asociado con el primero, lo configuraría a 0.5 segundos, lo que lo hace más grande reduce el uso de la CPU pero ralentiza la capacidad de respuesta, incrementando su uso de más CPU, para el segundo evento establecería un temporizador de 20 segundos.

Por supuesto, cuando el temporizador expira, no lo harías while 1 sino que solo recorrerás el cuerpo del bucle while una vez (es decir, deshazte de while).

Creo que no se pueden acoplar en un bucle while. tal vez necesite verificar la biblioteca de subprocesos o multiprocesamiento .

También hay un paquete llamado SimPy que también puedes ver. Las bibliotecas de subprocesamiento y multiprocesamiento también pueden ayudar.