[Python-es] computación paralela y concurrente

tny a.porrua en gmail.com
Sab Ene 1 05:56:57 CET 2011


> Hola. Antes de nada, feliz año! :D
> 
> He estado mirando la documentación de las bibliotecas que publicaste,
> y me genera una duda y ya que el lema es KISS, no seria mas simple
> usar un simple un "decorator class" para hacer esto lo que hace tu
> bibl. "fork"
> 
> Aquí un ejemplos:
> http://paste.niwi.be/17/raw/
> http://paste.niwi.be/18/raw/
> 
> Esta hecho con threads y ya se que no son escalables a múltiples
> núcleos, pero puedes substituirlo por "Process" y por casa llamada al
> método se generaría un proceso. Y no se si tu biblioteca tiene
> opciones de sincronizacion y la posibilidad de envío de mensajes entre
> procesos...(Lo digo que lo que viene de serie en python creo que es
> muchísimo mas completo y mas simple a mi parecer)


Mi biblioteca tiene dos partes, una que es para lanzar funciones y
ejecutar callbacks con sus valores de retorno, y otra que lanza procesos
que se comunican mediante eventos.

este ejemplo me parece muy kiss, creo que no necesita ni comentarios,
que se entiende sólo.

#!/usr/bin/env python
#-*- coding:utf-8 -*-
 
import hashlib
from pykiss import fork
 
usuarios = ['admin', 'good', 'pepe']
passwords = ['admin', '123456', 'password']
passw = '6f1a2f61d94139dbddc3238d4f46ce2f'
 
control = fork.Control()
 
def comprobar(usuario, password):
    if passw == hashlib.md5(usuario+'@'+password).hexdigest():
        return (usuario, password)
 
def mostrar(retorno):
    if retorno:
        print "User:%s\nPassword:%s"%retorno
 
for usuario in usuarios:
    for password in passwords:
        control.fork_function(mostrar, comprobar, usuario, password)
control.main()

Lo mismo con procesos que se envían eventos.

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import hashlib
from pykiss import fork
from pykiss import callback
import sys

usuarios = ['user', 'admin', 'good', 'pepe']
passwords = ['', 'admin', '123456','good', 'password']
passw = '6f1a2f61d94139dbddc3238d4f46ce2f'

control = fork.Control()

class Comprobar_Process(fork.Process):
	def __init__(self, unixsocket, user):
		fork.Process.__init__(self, unixsocket)
		self.instance_events['parar'] = self.parar
		self.user = user

	def parar(self, event):
		raise fork.Break_loop_exception()

	def main(self):
		for password in passwords:
			if passw == hashlib.md5(self.user+'@'+password).hexdigest():
				self.send_event(keyword = 'user en pass encontrado', user=self.user,
password=password)
				sys.exit()
			else:
				try:
					self.poll.do(0)
				except fork.Break_loop_exception:
					break
		self.send_event(keyword='process normaly ended',exit=0)
		sys.exit(0)

def encontrado(driver, event):
	print "User:%s\nPassword:%s"%(event['user'],event['password']) 
	for driver in control.drivers.itervalues():
		driver.send_event(keyword = 'parar')

control.events['user en pass encontrado'] = encontrado

for usuario in usuarios:
	control.fork(fork.Driver, callback.Callback(Comprobar_Process,
user=usuario))

control.main()

¿Cómo harías eso con decorator class y la biblioteca estandar?
¿Quedaría legible?

Cuando necesité trabajar con procesos leí y releí la biblioteca estandar
de python y te aseguro que me pareció demasiado complicado.
Ser demasiado completo está reñido con ser simple.
Así que hice sólo lo que necesitaba.

> 
> En el apartado de creación de excepciones, en mi opinión, no ayudas en nada...
> Creo que es mas simple:
> class MyError(Exception): pass
> 
> que:
> from pykiss.auto_exceptions import make_exception
> excepcion1 = make_exception('excepcion1')
> 
> Ademas de las excepciones pueden tener sus propios métodos y variables
> de instancia, que serian también mucho mas simples de definir como
> siempre se define que con el método de tu biblioteca.
> 
> Y antes de nada, como siempre, no quiero mal interpretaciones, solo
> genero una critica constructiva y no quiero ofender a nadie.
> 



con esto:
class MyError(Exception): pass

no puedes luego hacer así:
raise MyError(msg='ha pasado tal cosa', foo='tralari', bar='tralará)

para luego en el except hacer así
except MyError as e:
	print e.foo 

y con MyError = make_exception('MyError') si puedes hacer todo eso.

Pero tienes tu parte de razón, porque simplemente bastaba con 
class MyError(auto_exceptions.Base_exception): pass

A veces uno se obceca y va por el camino más dificil.
No sé cual quedará más legible...
Me lo pienso e igual cambio eso.


Todas son librerías que estaba usando yo en mis propios desarrollos,
porque lo encuentro más sencillo que hacerlo de otro modo, y me parecio
que podía ser de utilidad a más personas.
Así que las miré con lupa para eliminar cualquier bug que se me hubiera
escapado, y las comenté y documenté lo mejor que pude. 

> Un saludo.
> Andrei.
> 
> 

No ofendes, y agradezco tu crítica, aquí estamos todos para aprender.



Más información sobre la lista de distribución Python-es