Archive

Archive for August, 2009

multiprocessing.Pool i “Can’t pickle <type ‘instancemethod’>”

August 14th, 2009 No comments

Spędziłem właśnie chwilę na odkryciu tego, w jaki sposób w Pythonie, korzystając z puli procesów multiprocessing.Pool, przekazać metodę do wywołania, która jest metodą instancji, a nie po prostu funkcją w module. Korzystam z Pythona 2.5 i pakietu multiprocessing ściągniętego z PyPi w wersji 2.6.2.1.

Właściwy kod jest bardziej rozbudowany, i przede wszystkim wszystkie zależności pomiędzy klasami wstrzykiwane są przez Spring Pythona, ale uproszczona wersja dobrze ilustrująca sytuację jest poniżej. Istotne jest to, że od instancji klasy Handler nie mogę oczekiwać niczego innego ponad zdefiniowanie metody handle(self, message), nie mogę więc spodziewać się tego, że instancje te będą w jakikolwiek sposób customizowały picklowanie samych siebie.

Pierwsza próba, wyglądająca teoretycznie dobrze, wygląda tak:

from multiprocessing import Pool

class Handler(object):
    def handle(self, message):
        print message

class Listener(object):
    def __init__(self, pool, handler, message):
        self.pool = pool
        self.handler = handler
        self.message = message

    def run(self):
        self.pool.apply_async(self.handler.handle, self.message)

if __name__ == "__main__":

    import time

    pool = Pool(20)
    message = "Hello world!"

    listener = Listener(pool, Handler(), message)
    listener.run()

    time.sleep(3)

Jest to, niestety, wersja, której uruchomienie zakończy się pięknym wyjątkiem:

$ python cant-pickle.py
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python2.5/threading.py", line 486, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.5/threading.py", line 446, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/usr/lib/python2.5/site-packages/multiprocessing-2.6.2.1-py2.5-linux-i686.egg/multiprocessing/pool.py", line 225, in _handle_tasks
    put(task)
PicklingError: Can't pickle <type 'instancemethod'>: attribute lookup __builtin__.instancemethod failed

Poprawna wersja wygląda tak:

from multiprocessing import Pool

def handle(handler, message):
    handler.handle(message)

class Handler(object):
    def handle(self, message):
        print message

class Listener(object):
    def __init__(self, pool, handler, message):
        self.pool = pool
        self.handler = handler
        self.message = message

    def run(self):
        self.pool.apply_async(handle, [self.handler, self.message])

if __name__ == "__main__":

    import time

    pool = Pool(20)
    message = "Hello world!"

    listener = Listener(pool, Handler(), message)
    listener.run()

    time.sleep(3)

$ python test-cantpickle.py
Hello world!
$ 

Czyli jednak nie ma lekko, trzeba opakować metodę instancji w funkcję i dopiero wtedy przekazać do przetwarzania w puli, wtedy multiprocessing.Pool działa tak jak trzeba.

Swoją drogą, jeśli dostarczymy odpowiedniej pracy do wykonania to multiprocessing bardzo ładnie wysysa wszystkie core’y, więc historie, że Python nie jest w stanie korzystać ze wszystkich procesorów ze względu na GIL można spokojnie włożyć między bajki.

Share
Categories: Software Tags:

Poliglotyczne podcasty opensource’owe z pondjumpers.com

August 11th, 2009 No comments

Ciekawe podcasty serwują Panowie Greg Turnquist i Russ Miles. Na pondjumpers.com na razie można posłuchać o Springu, Pythonie i Spring Pythonie, Lifcie i Groovim. Autorzy są programistami poliglotami, a podcasty najwyraźniej dotyczą tego, na czym się dobrze znają, więc kolejne odcinki też powinny być miłe dla ucha. Dla twittujących jest z kolei @pondjumprs (w przeciwieństwie do @pondjumpers :-) ).

Share
Categories: Software Tags:

MO72, czyli zdalne runmqsc

August 9th, 2009 No comments

Wszyscy wiedzą, że przy hurtowym tworzeniu obiektów WebSphere MQ najlepiej posługiwać się poleceniem runmqsc, raczej nikomu nie przychodzi do głowy, żeby tworzyć 300 kolejek korzystając z WebSphere MQ Explorera lub – skądinąd całkiem niezłego – support packa MO71. Co jednak zrobić gdy queue manager znajduje się w systemie z/OS? Korzystanie z paneli ISPF do utworzenia kilkuset obiektów także nie należy do ciekawych zajęć. Co prawda można zestawić połączenia proxy pomiędzy queue managerami, i np. polecenia wysyłane do queue managera na Linuksie będą forwardowane do innego queue managera uruchomionego w systemie z/OS, ale jednak wymaga to dodatkowych zabiegów administracyjnych i jest kolejną rzeczą, o której trzeba pamiętać przy konfiguracji środowisk.

Na ratunek przychodzi freeware’owy support pack MO72, udostępniający polecenie mqsc, które najłatwiej można określić jako zdalne runmqsc. Dzięki MO72 możemy wywoływać polecenia MQSC na zdalnych queue managerach, w tym także na queue managerach zainstalowanych w systemie z/OS.

Przykładowe wywołanie MO72, sprawdzające przez kanał CRM.TO.EAI.1 głębokość kolejki S/CRM.TO.EAI.1 queue managera EAI.QM.1 uruchomionego na hoście 192.168.1.79, z listenerem uruchomionym na porcie 1424  wygląda tak

C:\>mqsc -m EAI.QM.1 -l -c CRM.TO.EAI.1 -h 192.168.1.79(1424) -C “DIS QLOCAL(S/CRM.TO.EAI.1) CURDEPTH”

Powyższe polecenie zadziała jednak tylko na systemach innych niż z/OS – dla queue managerów uruchomionych na z/OS-ach wymagane jest podanie switcha -z w wywołaniu polecenia. Zakładając więc, że mamy plik “zos-objects.mqsc”, w którym znajdują się polecenia CREATE QLOCAL tworzące kilkaset obiektów, w taki oto sposób można je szybko utworzyć na z/OS-ach:

C:\>mqsc -m EAI.QM.1 -l -z -c CRM.TO.EAI.1 -h 192.168.1.79(1424) < ./zos-objects.mqsc

Prawda, że jest to wygodniejsze niż panele? ;-)

Share
Categories: Software Tags: ,