Nota inicial: Si no te gusta python puede que este post te haga cambiar de opinión :)
Una de las mejoras de Python 2.6 (en estos momentos vamos por la 2.7, que será la última de la rama 2.x) es el módulo multiprocessing. En pocas palabras viene a ser un módulo para trabajar con procesos de la misma forma que se hace con threads, de hecho en un subconjunto de la funcionalidad puedes cambiar threads por procesos cambiando un solo import.
Sin embargo el módulo multiprocessing añade cosas muy interesantes como la posibilidad de trabajar con pool de procesos. Veamos un ejemplo.
Imaginemos que tenemos que bajar una serie de ficheros pdf para posteriormente extraer información de ellos. Una primera aproximación sería esta:
import urllib
import urllib2
reg\_nos = \[16738, 17288, 18162, 18776, 18868, 19116, 19223, 19505\];
pdf\_url = 'http://www.mapa.es/agricultura/pags/fitos/registro/sustancias/pdf/%s.pdf'
def fetch\_url(url, params={}):
return urllib2.urlopen(url).read()
def save\_url\_as\_file(url, filename):
open(filename,'wb').write(fetch\_url(url))
def download\_pdf(reg\_no):
f = '%d.pdf' % reg\_no
save\_url\_as\_file(pdf\_url % reg\_no, f)
print "\\t- %s downloaded" % f
\# tests
def single(regs):
for u in regs:
download\_pdf(u)
single(reg\_nos)
(puedes verlo mejor con sintáxis coloreada en github)
Para 4 míseros ficheros no merece la pena hacer más, pero imaginemos que queremos bajarnos miles y que además lo tenemos que hacer periódicamente, el tiempo en bajarse todos esos ficheros es alto. Lo primero que se nos ocurre es usar concurrencia: lanzando una serie de hilos/procesos que vayan bajando los ficheros aceleraría sensiblemente el proceso (de hecho así lo hacen los navegadores cuando se bajan los ficheros que referencia el HTML).
En python esto traducido a código ocupa mucho menos que explicarlo:
def download\_multi(regs, nprocesses=4):
pool = Pool(processes=nprocesses)
pool.map\_async(download\_pdf, regs).get()
Usando multiprocessing.Pool python se encarga de lanzar los procesos y preparar una cola para enviarle a la función que especificamos en el primer parámetro.
Este es un uso de multiprocessing, pero tiene otros muchos muy interesantes.
Podéis ver todo el código en github y ejecutar el pequeño benchmark:
q6:smll javi$ python fetch.py
- 16738.pdf downloaded
- 17288.pdf downloaded
- 18162.pdf downloaded
- 18776.pdf downloaded
- 18868.pdf downloaded
- 19116.pdf downloaded
- 19223.pdf downloaded
- 19505.pdf downloaded
2.30190205574
- 18776.pdf downloaded
- 17288.pdf downloaded
- 18162.pdf downloaded
- 16738.pdf downloaded
- 19116.pdf downloaded
- 18868.pdf downloaded
- 19505.pdf downloaded
- 19223.pdf downloaded
0.807252883911
Un incremento un poco menor de 4X, el número de procesos que lanzo en el pool.
Últimamente uso este módulo para muchísimas tareas ya que el uso es prácticamente directo si la aplicación está bien modularizada y permite aprovechar la potencia de las máquinas actuales (en mi caso un dual core).
Bonus Track - threads
Con threads también es posible hacerlo, pero lamentablemente el módulo threading no tiene la funcionalidad Pool, así que debemos emularla.
Antes de pasar a la implementeación está bien decir que desde hace cosa de dos años hasta ahora se ha criticado mucho el modelo multithread de python debido a que existe una cosa llamada GIL (Global Interpreter Lock) que hace que solo pueda estar ejecutándose un hilo al mismo tiempo en el intérprete python. A pesar de ser hilos nativos hay un lock que evita que dos hilos se puedan ejecutar al mismo tiempo. Si quieres saber un poco más sobre el GIL hay una presentación excelente de maestro Dave Beazley.
Es para llevarse las manos a la cabeza, pero esto no quiere decir que el desarrollo con hilos en python esté “prohibido”, símplemente hay que saber para qué se puede o no usar. En este caso el uso de threads, a pesar del Lock es muy interesante, ya que al ser tareas fundamentalmente de Entrada/Salida no hay problemas de bloqueo entre hilos (la explicación más en detalle en la presentación que he citado antes).
Sin más, usando Queue (otro módulo python mágico), una cola FIFO sincronizada la tarea es más o menos simple:
def threaded(regs, nthreads=4):
# ripped from http://www.dabeaz.com/generators/Generators.pdf
def consumer(q):
while True:
item = q.get()
if not item: break
download\_pdf(item)
in\_q = Queue.Queue()
# start threads
ths = \[threading.Thread(target=consumer,args=(in\_q,))
for th in xrange(nthreads)\]
for x in ths: x.start()
# put files to download
for i in regs:
in\_q.put(i)
# put end guards
for th in xrange(nthreads): in\_q.put(None)
# wait to finish
for x in ths: x.join()
El otro día estaba leyendo la realmente buena entrevista al creador de C++, Bjarne Stroustrup. No es el tema de este post, pero me ha parecido una entrevista de las que merece la pena repasar de vez en cuando, igual que el famoso discurso de Steve Jobs.
Creo que no podría estar más de acuerdo con lo que dice este hombre y suscribiría cada una de las frases, pero hay una que últimamente me da que pensar. En el último párrafo de la entrevista:
Know some non-computer field of study well — math, biology, history, optics, whatever. Learn to communicate effectively in speech and in writing. Spend an unreasonable amount of time on some difficult topic to really master it. Try to do something that might make a difference in the world.
Y es que en mi últimamente-más-activa faceta de comercial me he dado cuenta como hablando con gente de otros ámbitos, en concreto del agrícola, tienen una serie de problemas que como programador de corazón que soy pienso: “Si este señor supiese programar un mínimo haría maravillas”.
Me considero un privilegiado por tener conocimientos de un área muy diferente al de la programación y creo que es fundamental que el desarrollador tenga esos conocimientos. No pasa un día sin que vea a un desarrollador trabajando en cosas que no van a resolver ningún problema y casi siempre es porque no tienen la visión de la persona que tiene ese problema (o directamente porque no hay problema :). Además NO creo demasiado en el consultor que va al cliente, éste le explica su problema y le surge la solución mágica para su problema, siempre he creído que la solución correcta surge del verdadero entendimiento de la materia y eso solo pasa cuando estás a pie del cañón.
Además, no creo que haya cosa más reconfortante para un desarrollador es ver como algo que ha creado él se use para solucionar un problema.
Hace casi 4 meses mi fuerza de voluntad me retó y decidí empezar a hacer algo de deporte, no mucho, los excesos son malísimos, ya sabes. Decidí entonces empezar a correr, por suerte vivo en un pueblo y me permite salir fácilmente. Las razones que me impulsaron fueron varias:
- atrofiamiento absoluto. Años de estar sentado pasan factura y cuando al entrar y salir del coche haces el mismo sonido que un tío de 80 tacos algo en tu interior te dice que la cosa no está bien. Además estoy operado de corazón y quizás tenga que cuidar un poco estás cosas.
- pérdida de peso. Viene al hilo de lo anterior, si no te mueves y no cuidas bien lo que comes engordas (las matemáticas aquí funcionan muy bien :)
- tener una forma de distraerme: Últimamente he pasado demasiadas horas delante del monitor y no solo afecta físicamente. Siempre he escuchado que hacer deporte es una forma de desconectar muy buena.
- tenía un festejo familiar y tenía que meterme el traje de hace unos años. Esta no es la importante, pero si eres más agarrao que un chotis no es agradable comprarte un traje nuevo :).
Si estás pensando en empezar a hacer deporte te dejo algunos consejos que a mi me han ayudado:
- Ten cuidado, empieza poco a poco. Al comienzo de empezar a correr creo que me han dolido todas las articulaciones. Yo seguí, parcialmente el couch to 5k, no sé si será bueno o no, pero por lo menos propone un plan a seguir y parece razonable en cuanto a metas.
- Usa un buen calzado. De ir con unas zapatillas normales a unas en condiciones no hay color. Es de perogrullo, pero yo tardé en darme cuenta.
- Si eres un friki te puede amenizar el uso de alguna aplicación GPS que haga tracking de lo que haces (yo uso handy runner para android), usar un pulsómetro o cualquier otro elemento que te pueda dar números que analizar y comparar.
- Márcate alguna meta, por ejemplo correr todos los días la misma distancia o incrementar la distancia en X metros todos los días.
Después de 4 meses puedo hacer un análisis de los pro/cons:
- He conseguido que sea un hábito, me hace sentir mejor tanto física como mentalmente. Yo era de los que pensaba que la gente que salía a correr estaba loca, ahora les entiendo.
- Cuando empecé era imposible correr más de 1 minuto seguido y cuando llevaba 3km de camino estaba para el arrastre. Ahora puedo correr 7km a menos de 6 minutos por kilómetro sin problema, esto es con pulsaciones dentro de un margen razonable y sin sensación subjetiva de estar destrozado.
- Resulta que mucha gente que está a mi alrededor corre (y no lo sabía) y tengo un tema de conversación, además de que puedes salir juntos a correr.
- A medida que va pasando el tiempo ves como mejora tu forma, aunque es un proceso lento y a veces piensas que no está funcionando. De hecho durante los dos primeros meses pensaba: “cómo es posible que nadie diga que esto es sano”
- Entre las cosas malas han estado los momentos en los que me pasaba un poco y me dolían todas las articulaciones, pies, espalda… a menudo no desconecto y voy pensando cosas del trabajo mientras corro.
En resumen, es una meta no muy complicada de cumplir (no te quita más que una hora el día que sales a correr), que te hace sentir mejor y que para gente con una vida muy sedentaria, como es la de un programador, viene de perlas.
Si tienes algún consejo será bien recibido :) y si quieres quedar para echar unas carreras también :P.
No sé si es una cuestión solo de las empresas Españolas, no sé si es que en España las ofertas de trabajo sirven para más bien poco o qué, pero por lo general son un despropósito, llenas de sin sentidos,etc. Voy a dar mi punto de vista sobre como debería una empresa poner una oferta de trabajo si realmente quiere encontrar alguien de calidad (a partir de este punto la mitad de las empresas españolas habrán dejando de leer) o si símplemente no quieres hacer el ridículo:
- Nunca nunca dejes redactar una oferta técnica a una persona de RRHH. Por lo general no saben nada de tecnología y tienden a poner miles de siglas, muchas veces no tienen relación y dejan al descubierto que no sabes ni lo que haces.
- No digas que eres una “empresa lider del sector”. Si lo eres ya lo sabemos y si no lo eres también así que ahorratelo. No te preocupes, alguien de calidad va a mirar qué hace tu empresa antes de ir, así que pule el resto de la oferta para que se interesen.
- No me digas que es una empresa jóven, dinámica e innovadora. Si lo eres demuestralo, ahora hay herramientas como blogs, twitter, etc, donde se ve si eres o no eres. Tampoco montes un blog, una página de facebook y un twitter para ser molón porque se ve a la legua si eres más falso que Judas. Qué hay de malo en poner: “somos una empresa tradicional y hacemos lo de toda la vida, pero lo hacemos bien y tenemos los pies en la tierra”. Una vez fui a una entrevista y pregunté: “y qué tal es el ambiente de trabajo, la gente se lleva bien”, el entrevistador me respondió: “es una relación correcta entre compañeros”. Sí, aquella empresa era jóven, dinámica e innovadora.
- Ahorrate todo lo de, buscamos “persona responsable, autónoma, eficiente, analítica, con gran capacidad de trabajo en equipo, entusiasta, proactiva y blablbalbla”
- Se claro en lo que pides. Si quieres un programador que haga de todo un poco, pon que quieres un programador ninja, hay programadores que son así, modo rambo, llegan y resuelven. Si quieres alguien que sepa de una tecnología concreta, ponlo así, huye del “bueno, ya que estoy pongo perl, ruby, asm z80, asm 8087, JVM, dalvik, vim, emacs, turboC++, cobol, AS400 por si cuela”. Claro, para eso debes saber lo que quieres. Deja claras las responsabilidades.
- Dí claramente lo que ofrece tu empresa y cómo se gana la vida, de donde saca el dinero. Si lo sacas de subvenciones, es triste lo sabemos, pero ponlo, si es capital riesgo… o incluso si de verdad ganas dinero con lo que haces (no conozco empresas de software en España con este perfil)
- Si sabes, pon cual es el valor añadido que el empleado dará a la empresa. Si no aporto valor añadido, esto es, no se gana dinero conmigo, tarde o temprano terminarás por encargarme trabajo sin sentido, yo me cansaré y me iré. Habremos perdido tiempo y dinero los dos, así que piensalo bien. Deja ver además lo que puede aprender el empleado en tu empresa.
- Parece una obviedad: deja claro dónde es el trabajo, qué tipo de horario, si se puede trabajar en remoto, rango salarial, y en general toda la lógistica. Somos mayorcitos como para andar perdiendo el tiempo.
- Usa algo diferente, por ejemplo, dropbox hace cosas como esta y en algunas ofertas suyas he visto como mandan resolver un problema de programación que más o menos cualquier programador con cierta experiencia sabe resolver. Con esto demuestras que sabes (para poner un problema hay que conocer bien la materia) y sabes que el que envía el CV está realmente interesado y algo de su forma de trabajo. Pide por ejemplo su cuenta en github, trabajos anteriores, o no pidas el currículum (leer el footer de esta oferta de trabajo de linkingpaths)
En resumen, sé claro, sincero y si no tienes ni idea intenta que no se note mucho.
Si hay una cosa que fideliza, que agrada al consumidor es la buena atención al cliente. Aunque tu producto no sea el mejor, si tienes una buena atención terminas enamorando. He escuchado mil veces lo típico de “fui a XXXXXX, no era de lo mejor, pero me han tratado estupendamente” o “he comprado XXXXX se me estropeó, pero en 1 día me lo han enviado reparado”.
Y si es tan fácil tener al una persona contenta, por qué las operadoras, por poner un ejemplo, son el claro ejemplo de la mala atención al cliente?. Que tire la primera piedra el que nunca se haya quejado de su ADSL, su factura de móvil que han tardado lustros en solucionar. La respuesta es que NO es tan fácil.
Para tener una buena atención al cliente hay que tener gente que sepa darla, así de claro, así de fácil y así de difícil a su vez. Por un lado el cliente debe tener claro donde acudir, debe haber alguien que le atienda (y NO acepto una máquina como alguien), que sepa escucharle y que además sepa que hacer. Esto es, alguien que:
- sepa de lo que está hablando, no una persona que sigue un guión de preguntas,
- que sepa a quien acudir en caso de tal o cual problema
- que sepa resolver los principales problemas él solito,
- que se encargue de ese problema, tanto de estar pendiente del cliente como de que ese problema llegue a quien tiene que llegar para que se resuelva para que en la medida de lo posible no vuelva a pasar. A veces aunque no te resuelvan el problema, si ves que están pendientes de él el cabreo ese que te envenena se va. Un simple SMS con “Hola Javi, estamos trabajando en tu problema con la conexión ADSL. Te llamamos cuando sepamos algo. Fdo: Perico”.
Pero no, tener a gente formada y preparada exige tiempo y dinero, y es mucho más fácil ir al país más desfavorecido que hable tu idioma y poner a los que menos cobren a trabajar sin ningún tipo de formación, sin saber de lo que hablan.
La próxima vez que vayas a comprar algo, no solo pienses en lo que compres, piensa en qué hay detrás de ese coste.
Y por último, hay una cosa en lo que creo que muchas empresas deberían espabilar y es en ser transparentes, no solo con qué hacen y cómo (hasta cierto punto) si no como tratan al cliente con sus problemas.