<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-18135354</id><updated>2012-01-30T18:03:43.036-02:00</updated><category term='linux'/><category term='generators'/><category term='puremvc'/><category term='poo'/><category term='funcional'/><category term='decorator'/><category term='genetic algorithms'/><category term='pkcs23'/><category term='pygtk'/><category term='gtk'/><category term='python2.3'/><category term='django'/><category term='fibonacci'/><category term='mvc'/><category term='design pattern'/><category term='maemo'/><category term='pdb'/><category term='socket'/><category term='ctypes'/><category term='glade'/><category term='nokia'/><category term='web2.0'/><category term='python'/><category term='metaclass'/><category term='private_key'/><category term='ssl'/><category term='kiwi'/><category term='qt'/><category term='phi'/><category term='recursivo'/><category term='pypy'/><category term='sort'/><category term='cert'/><title type='text'>Ni</title><subtitle type='html'>Python, Ruby, Javascript, FreeBSD, GNU/Linux, MongoDB, PostgreSQL e Sci-Fi.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://victorpoluceno.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18135354/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://victorpoluceno.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Victor Godoy Poluceno</name><uri>http://www.blogger.com/profile/17775902426597865021</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-x0AJ0RNWXI4/TgTOYCzjEFI/AAAAAAAAABA/l5rWzOjef7Q/s220/avatar.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>13</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-18135354.post-7381308743391135498</id><published>2009-07-06T11:52:00.005-03:00</published><updated>2009-07-06T12:58:47.361-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='nokia'/><category scheme='http://www.blogger.com/atom/ns#' term='gtk'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='qt'/><category scheme='http://www.blogger.com/atom/ns#' term='maemo'/><title type='text'>Nokia vai mudar para Qt no Maemo</title><content type='html'>Como já era esperado a Nokia &lt;a href="http://flors.wordpress.com/2009/07/05/maemo-harmattan-keynote-at-gcds/"&gt;anunciou&lt;/a&gt; durante o &lt;a href="http://www.grancanariadesktopsummit.org/"&gt;GCDS&lt;/a&gt; que o Maemo 6 (Harmattan) vai trocar o GTK pelo Qt. Embora o Gnome Mobile continue sendo a base do sistema, a interface com usuário passa a utilizar Qt. Essa mudança era esperada devido a compra da &lt;a href="http://www.qtsoftware.com/"&gt;Trolltech&lt;/a&gt; pela Nokia. &lt;br /&gt;&lt;br /&gt;Mesmo sendo uma decisão esperada, ao meu ver a Nokia parece complicar ainda mais o já ruim processo de aceitação do Maemo e seus Internet Table NXXX pelo mercado. O atual Maemo 5 que ainda não foi lançado, foi basicamente reconstruído utilizando GTK/Clutter mudando totalmente a interface em relação ao seu antecessor o Maemo 4 que era basicamente GTK. Agora na próxima versão mais mudanças na interface com adoção do Qt.&lt;br /&gt;&lt;br /&gt;O GTK ainda vai estar disponível no Maemo mantido pela comunidade, garantindo que aplicativos legados continuem funcionando mesmo que com visual diferente do sistema. Trocar de GTK para Qt não é uma simples mudança de ui toollkit mas também de linguagem já que Qt se baseia em C++ e GTK em C, ou seja, uma grande mudança para todos os desenvolvedores.&lt;br /&gt;&lt;br /&gt;Na minha opnião, a Nokia mostra mais uma vez que as decisões em relação ao Maemo são tomados mais por diretores sem conhecimento e menos pelos técnicos ou ao menos demonstra que existe pouca sinergia entre esses dois grupos, já que não ter GSM no N810 e mudar completamente sua interface a cada versão não anima desenvolvedores para produzir aplicativos para essa plataforma e não traz novos usuários.&lt;br /&gt;&lt;br /&gt;Tudo bem, Qt é uma excelente biblioteca, mas na minha opinião essa mudança já deveria ter sido feita no Maemo 5, evitando que novos aplicativos para o Maemo 5 tenham que portardos em seguida para o Maemo 6 quando estiver utilizando Qt.&lt;br /&gt;&lt;br /&gt;Maemo é uma excelente plataforma e meu sonho de consumo é o futuro N900 assim que for lançado, mas espero que a Nokia tenho um pouco mais de cuidado com suas decisões em relação ao Maemo, afinal Android e Moblin estão criando excelentes plataformas.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18135354-7381308743391135498?l=victorpoluceno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://victorpoluceno.blogspot.com/feeds/7381308743391135498/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18135354&amp;postID=7381308743391135498' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18135354/posts/default/7381308743391135498'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18135354/posts/default/7381308743391135498'/><link rel='alternate' type='text/html' href='http://victorpoluceno.blogspot.com/2009/07/nokia-vai-mudar-para-qt-no-maemo.html' title='Nokia vai mudar para Qt no Maemo'/><author><name>Victor Godoy Poluceno</name><uri>http://www.blogger.com/profile/17775902426597865021</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-x0AJ0RNWXI4/TgTOYCzjEFI/AAAAAAAAABA/l5rWzOjef7Q/s220/avatar.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18135354.post-352186786753511962</id><published>2009-06-30T15:18:00.003-03:00</published><updated>2009-06-30T15:47:07.524-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='genetic algorithms'/><title type='text'>Sounding the Stars with Genetic Algorithms</title><content type='html'>Eu tenho muito interesse em computação aplicada na resolução de problemas reias, essa palestra que aconteceu no Google &lt;a href="http://www.youtube.com/watch?v=r4O10PSp7Dc"&gt;Sounding the Stars with Genetic Algorithms&lt;/a&gt; é um excelente exemplo. &lt;br /&gt;&lt;br /&gt;O autor mostra um processo computacional automatizado utilizando &lt;a href="http://en.wikipedia.org/wiki/Genetic_algorithm"&gt;Genetic Algorithm&lt;/a&gt; na busca de vida extraterrestre inteligente,  comparando a freqüência emitida pelos astros com modelos conhecidos. &lt;br /&gt;&lt;br /&gt;Mais vídeos como este em &lt;a href="http://research.google.com/video.html://"&gt;Google Research Tech Talks at Google&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18135354-352186786753511962?l=victorpoluceno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://victorpoluceno.blogspot.com/feeds/352186786753511962/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18135354&amp;postID=352186786753511962' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18135354/posts/default/352186786753511962'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18135354/posts/default/352186786753511962'/><link rel='alternate' type='text/html' href='http://victorpoluceno.blogspot.com/2009/06/sounding-stars-with-genetic-algorithms.html' title='Sounding the Stars with Genetic Algorithms'/><author><name>Victor Godoy Poluceno</name><uri>http://www.blogger.com/profile/17775902426597865021</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-x0AJ0RNWXI4/TgTOYCzjEFI/AAAAAAAAABA/l5rWzOjef7Q/s220/avatar.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18135354.post-7833534869796817324</id><published>2008-10-30T13:44:00.008-02:00</published><updated>2008-10-30T14:45:00.988-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gtk'/><category scheme='http://www.blogger.com/atom/ns#' term='decorator'/><category scheme='http://www.blogger.com/atom/ns#' term='glade'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='pygtk'/><title type='text'>Decorators com argumentos</title><content type='html'>Nos últimos tempos estive escrevendo uma API que utiliza &lt;span style="font-weight:bold;"&gt;decorators&lt;/span&gt; para registrar eventos em uma aplicação &lt;span style="font-weight:bold;"&gt;PyGTK/Glad&lt;/span&gt;e. Nessa API basicamente eu tenho eventos registrados no &lt;span style="font-weight:bold;"&gt;glade&lt;/span&gt; e associados a um &lt;span style="font-weight:bold;"&gt;handler&lt;/span&gt; na aplicação (glade.sinal_connect('event', handler)) e eventos conectados diretamente na aplicação associados a um &lt;span style="font-weight:bold;"&gt;handler&lt;/span&gt; e um &lt;span style="font-weight:bold;"&gt;widget&lt;/span&gt; (widget.connect('event', handler)).&lt;br /&gt;&lt;br /&gt;Então precisei de um &lt;span style="font-weight:bold;"&gt;decorator&lt;/span&gt; que em alguns momentos não receberia nenhum parâmetro, associando a função decorada a um sinal registrado no &lt;span style="font-weight:bold;"&gt;glade&lt;/span&gt; com o mesmo nome da função.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# Associa a função 'destroy' ao evento 'destroy' já registrado no glade&lt;br /&gt;&lt;br /&gt;@handler&lt;br /&gt;def destroy(self, *args):&lt;br /&gt;    print args&lt;br /&gt;&lt;br /&gt;# Mesmo funcionamento&lt;br /&gt;&lt;br /&gt;@handler()&lt;br /&gt;def destroy(self, *args):&lt;br /&gt;    print args&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ou ainda, este mesmo &lt;span style="font-weight:bold;"&gt;decorator&lt;/span&gt; poderia receber argumentos detalhando qual o nome do evento e &lt;span style="font-weight:bold;"&gt;widget&lt;/span&gt; para quais a função decorada deve ser associada.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# Associa a função 'x' ao evento 'destroy' já registrado no glade&lt;br /&gt;&lt;br /&gt;@handler('destroy')&lt;br /&gt;def x(self, *args):&lt;br /&gt;    print args&lt;br /&gt;&lt;br /&gt;# Associa a função y ao evento 'on_bt_ok_clicked' no widget bt_ok&lt;br /&gt;&lt;br /&gt;@handler('on_bt_ok_clicked', bt_ok)&lt;br /&gt;def y(self, *args):&lt;br /&gt;    print args&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Quando nenhum argumento é informado (@decorator()) utilizo uma função aninhada para ser retornada como &lt;span style="font-weight:bold;"&gt;decorator&lt;/span&gt; e assim efetivamente decorar a função. O mesmo funcionamento se aplica quando os argumentos não são funções ou métodos (@decorator('x'), @decorator('x', a=1)), utilizando o módulo &lt;span style="font-weight:bold;"&gt;inspect&lt;/span&gt; . Esse comportamento só muda quando o &lt;span style="font-weight:bold;"&gt;decorator&lt;/span&gt; não recebe parâmetros, ou seja, quando este não é invocado, retornando a função ou método recebido sem nenhuma modificação.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def decorator(*args, **kargs):&lt;br /&gt;    import inspect&lt;br /&gt;    # @decorator() or @decorator('x') or @decorator('x', d='a')&lt;br /&gt;    if not args or not inspect.isroutine(args[0]): &lt;br /&gt;        def deco(func):&lt;br /&gt;            def wrapper(*f_args, **f_kargs):&lt;br /&gt;                return func(*f_args, **f_kargs)&lt;br /&gt;            return wrapper&lt;br /&gt;        return deco&lt;br /&gt;    elif inspect.isroutine(args[0]): # @decorator&lt;br /&gt;        return args[0]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Exemplos de uso:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;@decorator&lt;br /&gt;def d(x, y, d=1):&lt;br /&gt;    print x, y, d&lt;br /&gt;#d = decorator(d)&lt;br /&gt;&lt;br /&gt;@decorator()&lt;br /&gt;def e(x, y, d=1):&lt;br /&gt;    print x, y, d&lt;br /&gt;#e = decorator()(e)&lt;br /&gt;&lt;br /&gt;@decorator('x')&lt;br /&gt;def f(x, y, d=1):&lt;br /&gt;    print x, y, d&lt;br /&gt;#f = decorator('x')(f)&lt;br /&gt;&lt;br /&gt;@decorator('x', d=5)&lt;br /&gt;def g(x, y, d=1):&lt;br /&gt;    print x, y, d&lt;br /&gt;#f = decorator('x', d=5)(g)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Abaixo o mesmo &lt;span style="font-weight:bold;"&gt;decorator&lt;/span&gt; utilizando classe, assim o comportamento do &lt;span style="font-weight:bold;"&gt;decorator&lt;/span&gt; pode ser facilmente expandido para funcionar com métodos seguindo esse texto &lt;a href="http://blog.ianbicking.org/2008/10/24/decorators-and-descriptors/"&gt;Decorators and Descriptors&lt;/a&gt;, fazendo o &lt;span style="font-weight:bold;"&gt;decorator&lt;/span&gt; ser ainda mais flexível podendo ser utilizado com funções ou métodos ao mesmo tempo:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class decorator(object):&lt;br /&gt;    def __init__(self, *args, **kargs):&lt;br /&gt;        import inspect&lt;br /&gt;        # @decorator() or @decorator('x') or @decorator('x', d='a')&lt;br /&gt;        if not args or not inspect.isroutine(args[0]): &lt;br /&gt;            def deco(func):&lt;br /&gt;                def wrapper(*f_args, **f_kargs):&lt;br /&gt;                    return func(*f_args, **f_kargs)&lt;br /&gt;                return wrapper&lt;br /&gt;            self.func = deco&lt;br /&gt;        elif inspect.isroutine(args[0]): # @decorator&lt;br /&gt;            self.func = args[0]&lt;br /&gt;&lt;br /&gt;    def __call__(self, *args, **kargs):&lt;br /&gt;        return self.func(*args, **kargs)&lt;br /&gt;&lt;br /&gt;    def __get__(self, obj, type=None):&lt;br /&gt;        if obj is None:&lt;br /&gt;            return self&lt;br /&gt;        new_func = self.func.__get__(obj, type)&lt;br /&gt;        return self.__class__(new_func)    &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Exemplos de uso:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class A:&lt;br /&gt;    @decorator&lt;br /&gt;    def b(self, x, y):&lt;br /&gt;        print x, y&lt;br /&gt;&lt;br /&gt;a = A()&lt;br /&gt;a.b(1, 2)&lt;br /&gt;&lt;br /&gt;@decorator&lt;br /&gt;def b(x, y):&lt;br /&gt;    print x, y&lt;br /&gt;&lt;br /&gt;b(2, 3)&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18135354-7833534869796817324?l=victorpoluceno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://victorpoluceno.blogspot.com/feeds/7833534869796817324/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18135354&amp;postID=7833534869796817324' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18135354/posts/default/7833534869796817324'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18135354/posts/default/7833534869796817324'/><link rel='alternate' type='text/html' href='http://victorpoluceno.blogspot.com/2008/10/decorators-com-argumentos.html' title='Decorators com argumentos'/><author><name>Victor Godoy Poluceno</name><uri>http://www.blogger.com/profile/17775902426597865021</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-x0AJ0RNWXI4/TgTOYCzjEFI/AAAAAAAAABA/l5rWzOjef7Q/s220/avatar.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18135354.post-8429443017383297069</id><published>2008-09-26T11:24:00.017-03:00</published><updated>2008-10-02T10:10:04.576-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='puremvc'/><category scheme='http://www.blogger.com/atom/ns#' term='mvc'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='metaclass'/><title type='text'>Python e MVC - Parte 2</title><content type='html'>Continuando o post anterior &lt;a href="http://victorpoluceno.blogspot.com/2008/09/python-e-mvc-parte-1.html"&gt;Python e MVC - Parte 1&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Durante o desenvolvimento de uma aplicação aqui na empresa estive decidido a utilizar um framework MVC para Python que além de me prover as ferramentas necessárias para resolver os meus dilemas de design como manutenção facilitada, separação da aplicação em partes lógicas e criação de uma estrutura de componentes este também deveria ser genérico o suficiente para permitir a troca da view na minha aplicação de maneira simples e fácil.&lt;br /&gt;&lt;br /&gt;O problema é que hoje existem basicamente três frameworks MVC para Python: &lt;a href="http://www.async.com.br/projects/kiwi/"&gt;Kiwi&lt;/a&gt;, &lt;a href="http://pygtkmvc.sourceforge.net/"&gt;pygtkmvc&lt;/a&gt; e &lt;a href="http://trac.puremvc.org/PureMVC_Python"&gt;PureMVC&lt;/a&gt;. O Kiwi é um framework muito bom e desenvolvido para uma aplicação real o &lt;a href="http://www.stoq.com.br/"&gt;Stoq&lt;/a&gt;, o pygtkmvc apesar de ter idéias interessantes parece ser um projeto abandonado e o PureMVC por sua vez é um projeto iniciado em ActionScript que mais tarde foi portado para diversas linguagens entre elas Python.&lt;br /&gt;&lt;br /&gt;O Kiwi e o pygtkmvc são altamente acoplados com a view no caso &lt;a href="http://www.pygtk.org/"&gt;PyGtk&lt;/a&gt;, o que vai totalmente contra o princípio de fraco acoplamento entre as partes como diz o &lt;a href="http://pt.wikipedia.org/wiki/MVC"&gt;MVC&lt;/a&gt;, e isso IMHO é muito importante e também é um requisito da minha aplicação. Sendo assim, sobra apenas nosso amigo PureMVC.&lt;br /&gt;&lt;br /&gt;Eu também poderia construir meu próprio framework MVC, de acordo com minhas necessidades e me baseando nestes últimos três exemplos, reunindo assim o melhor de cada um. Sem dúvida, essa seria a melhor alternativa, mas como sempre o tempo era curto e essa não era uma possibilidade. Sem falar no esforço enorme de análise e um conhecimento muito profundo de design patterns necessário para se criar algo genérico o suficiente.&lt;br /&gt;&lt;br /&gt;O PureMVC possui alguns problemas, IMHO. O primeiro problema é seu estilo ou filosofia e sua nomenclatura que são extremamente diferentes do que estamos acostumados em Python. A implementação então nem se fala, obviamente foi feita por um programador Java ou algo do tipo, embora funcione.&lt;br /&gt;&lt;br /&gt;Algumas coisas não seguem uma linha de simplicidade e facilidade no uso, tornando coisas simples um pouco complexas demais. Como exemplo, o código abaixo foi retirado do demo do projeto que utiliza wxPython:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class ProductListMediator(Mediator, IMediator):&lt;br /&gt;    NAME = "ProductListMediator"&lt;br /&gt;    product_proxy = None&lt;br /&gt;    def __init__(self, view_component):&lt;br /&gt;        self.view_component = view_component&lt;br /&gt;        super(ProductListMediator, self).__init__(self.NAME, view_component)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O código acima pode ser simplicado com uma meta class como essa:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class MetaMediator(type):&lt;br /&gt;    def __init__(cls, name, bases, namespace):&lt;br /&gt;        cls.NAME = name&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;class BaseMediator(Mediator, IMediator):&lt;br /&gt;    __metaclass__ = MetaMediator&lt;br /&gt;    def __init__(self, view_component=None, constant_list=[]):&lt;br /&gt;        self.constant_list = constant_list&lt;br /&gt;        super(BaseMediator, self).__init__(self.NAME, view_component)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Obtendo o mesmo resultado que o código original sem perder em flexibilidade:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class ProductListMediator(BaseMediator):&lt;br /&gt;    product_proxy = None&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O PureMVC reune uma gama de padrões em uma solução bem interessante. Todas as partes do MVC são agrupadas e invocadas por um padrão &lt;a href="http://en.wikipedia.org/wiki/Facade_pattern"&gt;facade&lt;/a&gt;, este facade invoca o controller através do padrão &lt;a href="http://en.wikipedia.org/wiki/Command_pattern"&gt;command&lt;/a&gt; utilizando um esquema de execução por variáveis globais, com essa solução o controller não fica acoplado ao facade, já que se o nome do método for alterado, basta alterar em um local, no alias definido na variável global. &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class AppFacade(Facade):&lt;br /&gt;    ON_ACT_STARTUP = 'on_act_startup'&lt;br /&gt;&lt;br /&gt;    @staticmethod&lt;br /&gt;    def getInstance():&lt;br /&gt;        return AppFacade()&lt;br /&gt;&lt;br /&gt;    def initializeController(self):&lt;br /&gt;        super(AppFacade, self).initializeController()&lt;br /&gt;        super(AppFacade, self).registerCommand(AppFacade.ON_ACT_STARTUP,\&lt;br /&gt;            controller.StartupCommand)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O controller por sua vez utiliza o padrão &lt;a href="http://en.wikipedia.org/wiki/Observer_pattern"&gt;observer&lt;/a&gt; para se comunicar com a view garantido fraca acoplamento com o uso de notificações. &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class DeleteCommand(SimpleCommand, ICommand):&lt;br /&gt;    def execute(self, note):&lt;br /&gt;        product = note.getBody()&lt;br /&gt;        product_proxy = self.facade.retrieveProxy(model.ProductProxy.NAME)&lt;br /&gt;        product_proxy.delete(product)&lt;br /&gt;        self.facade.sendNotification(main.AppFacade.ON_PRODUCT_DELETE)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A view então utilizando o padrão &lt;a href="http://en.wikipedia.org/wiki/Mediator_pattern"&gt;mediator&lt;/a&gt; para se comunicar com a visão concreta Gtk, Html, etc mantem mais uma vez acoplamento fraco, se for preciso mudar de Gtk para Html ou Qt, muito pouco do código precisará ser modificado, sanando a minha necessidade inicial. &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class DialogMediator(Mediator, IMediator):&lt;br /&gt;    NAME = "DialogMediator"&lt;br /&gt;    def __init__(self, view_component):&lt;br /&gt;        self.view_component = view_component&lt;br /&gt;  &lt;br /&gt;    def listNoticationInterests(self):&lt;br /&gt;        return [main.AppFacade.ON_SHOW_DIALOG,]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;E por fim o model utiliza o padrão &lt;a href="http://en.wikipedia.org/wiki/Proxy_pattern"&gt;proxy&lt;/a&gt; para garantir abstração por interface, assim proporcionando independência da tecnologia utilizada no model, ORM, XML, serialização, etc.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class ProductProxy(Proxy):&lt;br /&gt;    NAME = "ProductProxy"&lt;br /&gt;    def __init__(self):&lt;br /&gt;        super(ProductProxy, self).__init__(self.NAME, [])&lt;br /&gt;&lt;br /&gt;    def get_all(self):&lt;br /&gt;        return value_object.ProductVO.query.all()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O esquema utilizado pelo PureMVC é um tanto complexo a primeira vista, mas se for utilizado com bom senso e sempre com simplicidade em mente o retorno pode ser muito positivo. Além da fraco acoplamento a manutenção fica muito fácil, já que cada entidade da aplicação fica bem separada evitando propagação de erros pela aplicação. Vale lembrar que o PureMVC funciona como um esqueleto para sua aplicação não obrigando o uso explicito de todos os componentes.&lt;br /&gt;&lt;br /&gt;Como o PureMVC é feito para um conjunto de linguagens ao qual o Python não se encaixa, uma camada acima do PureMVC se faz necessária afim de simplificar a utilização deste e excluindo as partes desnecessárias, como os exemplos mostrados acima.&lt;br /&gt;&lt;br /&gt;Uma dica é simplificar o esquema de notificações do mediator para que as notificações executem os métodos da classe implementa o mediator que tiverem o mesmo nome das notificações, excluindo assim a necessidade do registro e criação das notificações na classe. Como exemplo abaixo, retirado da mesma demo:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def listNotificationInterests(self):&lt;br /&gt;    return [&lt;br /&gt;        main.AppFacade.ON_PRODUCT_CHANGE,&lt;br /&gt;        main.AppFacade.ON_PRODUCT_DELETE,&lt;br /&gt;    ]&lt;br /&gt;&lt;br /&gt;def handleNotification(self, note):&lt;br /&gt;    if note.getName() in [main.AppFacade.ON_PRODUCT_CHANGE, main.AppFacade.ON_PRODUCT_DELETE]:&lt;br /&gt;        self.view_component.clear()&lt;br /&gt;        self.view_component.fill(self.product_proxy.get_all())&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Neste parte de código o programador precisa especificar quais as notificações a classe recebe e escrever um método com um monte de condicionais para tratar cada notificação. É muito mas fácil escrever uma metaclass para transformar isso em um esquema de sinal que invoca o sinal que tiver um método na classe com o mesmo nome do sinal.&lt;br /&gt;&lt;br /&gt;Fica na minha lista de coisas a fazer uma versão deste framework para Python, com um código e uma filosofia adaptada ao estilo Python de ser.&lt;br /&gt;&lt;br /&gt;Por fim um &lt;a href="http://joelhooks.com/2008/03/15/5-reasons-puremvc-kicks-ass/"&gt;link&lt;/a&gt; interessante sobre o PureMVC.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18135354-8429443017383297069?l=victorpoluceno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://victorpoluceno.blogspot.com/feeds/8429443017383297069/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18135354&amp;postID=8429443017383297069' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18135354/posts/default/8429443017383297069'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18135354/posts/default/8429443017383297069'/><link rel='alternate' type='text/html' href='http://victorpoluceno.blogspot.com/2008/09/python-e-mvc-parte-2.html' title='Python e MVC - Parte 2'/><author><name>Victor Godoy Poluceno</name><uri>http://www.blogger.com/profile/17775902426597865021</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-x0AJ0RNWXI4/TgTOYCzjEFI/AAAAAAAAABA/l5rWzOjef7Q/s220/avatar.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18135354.post-6724738444426215522</id><published>2008-09-18T16:41:00.024-03:00</published><updated>2008-09-19T16:24:10.186-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='poo'/><category scheme='http://www.blogger.com/atom/ns#' term='metaclass'/><title type='text'>Papo de programador</title><content type='html'>Eu: The class of a class is ...&lt;br /&gt;&lt;br /&gt;Programador X: Humm.... another class?&lt;br /&gt;&lt;br /&gt;Eu: Não.&lt;br /&gt;&lt;br /&gt;Depois de muitas respostas "interessantes"..&lt;br /&gt;&lt;br /&gt;Programador Z: Pesquisei no google, é uma &lt;a href="http://www.voidspace.org.uk/python/articles/five-minutes.shtml"&gt;metaclass&lt;/a&gt;, mas o que é uma metaclass?&lt;br /&gt;&lt;br /&gt;Programador Y: Simplificando é uma classe que serve para construir outra classe.&lt;br /&gt;&lt;br /&gt;Programador W: Eu uso VI para construir uma classe, então o VI é uma metaclass.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18135354-6724738444426215522?l=victorpoluceno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://victorpoluceno.blogspot.com/feeds/6724738444426215522/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18135354&amp;postID=6724738444426215522' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18135354/posts/default/6724738444426215522'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18135354/posts/default/6724738444426215522'/><link rel='alternate' type='text/html' href='http://victorpoluceno.blogspot.com/2008/09/papo-de-programador.html' title='Papo de programador'/><author><name>Victor Godoy Poluceno</name><uri>http://www.blogger.com/profile/17775902426597865021</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-x0AJ0RNWXI4/TgTOYCzjEFI/AAAAAAAAABA/l5rWzOjef7Q/s220/avatar.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18135354.post-3579004464988468458</id><published>2008-09-18T16:41:00.018-03:00</published><updated>2008-09-19T16:06:13.169-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='puremvc'/><category scheme='http://www.blogger.com/atom/ns#' term='kiwi'/><category scheme='http://www.blogger.com/atom/ns#' term='design pattern'/><category scheme='http://www.blogger.com/atom/ns#' term='mvc'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Python e MVC - Parte 1</title><content type='html'>É fato que durante o desenvolvimento de uma aplicação mais complexa alguns problemas ou dilemas&lt;br /&gt;podem fazer nosso cérebro fritar. Para que o programador alcance uma boa solução é recomendável&lt;br /&gt;que ele se concentre no contexto do problema e da solução. &lt;span style="font-weight:bold;"&gt;Python&lt;/span&gt; alcança esse objetivo de maneira magnífica, com um alto nível de abstração, simplicidade e coesão a linguagem permite que o programador se desvincule da linguagem e fique livre para se focar na solução.&lt;br /&gt;&lt;br /&gt;No entanto, alguns problemas não fazem parte do contexto do problema e da solução, estes geralmente são ocasionados por nós mesmos, seja por falta de conhecimento da linguagem em questão, de organização, planejamento ou ainda pelo uso de uma solução pouco elegante ou inadequada.&lt;br /&gt;&lt;br /&gt;Um sistema que se inicia de maneira desorganizada e sem planejamento com o passar do tempo e com evolução natural do mesmo, tende a enfrentar dificuldades assustadoras em relação a manutenção.&lt;br /&gt;&lt;br /&gt;Qual a solução? Simples, vamos nos organizar, planejando e definindo muito bem como nosso sistema deve ser feito, vamos utilizar um bom processo de analise e pronto! Esse já é um grande passo, mas além desses pontos precisamos nos perguntar, será que os problema que estou tentando resolver já não possuem uma solução?&lt;br /&gt;&lt;br /&gt;Sim, alguns problemas já possuem soluções "amplamente" divulgadas e aceitas, essas soluções são chamadas de &lt;a href="http://en.wikipedia.org/wiki/Design_Patterns"&gt;Design patterns (Padrões de projeto)&lt;/a&gt; ou &lt;a href="http://en.wikipedia.org/wiki/Architectural_pattern_(computer_science)"&gt;Architectural patterns (Padrões de arquitetura de software)&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;O &lt;a href="http://en.wikipedia.org/wiki/Model-view-controller"&gt;MVC&lt;/a&gt; (model, view, controller) é um padrão de arquitetura que serve para separar conceitos lógicos da sua aplicação. O grande problema é que o próprio &lt;span style="font-weight:bold;"&gt;MVC&lt;/span&gt;, como todo padrão, por si só, não resolve todos os problemas e algumas vezes pode acabar criando outros problemas. O uso ideal de &lt;span style="font-weight:bold;"&gt;MVC&lt;/span&gt; com alguns cuidados e uma série de padrões de projeto pode nos garantir uma aplicação muito bem escrita e de fácil manutenção.&lt;br /&gt;&lt;br /&gt;Inicialmente utilizar &lt;span style="font-weight:bold;"&gt;MVC&lt;/span&gt; e outros padrões fielmente pode ser um tanto chato e cansativo, mas como o tempo esse esforço pode render bons frutos. Aliar esses padrões com a simplicidade e elegância do &lt;span style="font-weight:bold;"&gt;Python&lt;/span&gt; não é um equilíbrio tão fácil de se alcançar, mas que pode ser muito gratificante.&lt;br /&gt;&lt;br /&gt;Quando utilizo algum padrão em &lt;span style="font-weight:bold;"&gt;Python&lt;/span&gt; sempre procuro ter em mente que este padrão pode não se aplicar em &lt;span style="font-weight:bold;"&gt;Python&lt;/span&gt;, ou seja, tento não aceitar esses padrões como únicas e infalíveis soluções.&lt;br /&gt;&lt;br /&gt;No próximo post vou falar sobre os &lt;span style="font-weight:bold;"&gt;frameworks MVC para Python (&lt;a href="http://www.async.com.br/projects/kiwi/"&gt;Kiwi&lt;/a&gt;, &lt;a href="http://puremvc.org/component/option,com_wrapper/Itemid,168/"&gt;PureMVC&lt;/a&gt;, etc)&lt;/span&gt;, quais as opções e detalhes de implementação.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18135354-3579004464988468458?l=victorpoluceno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://victorpoluceno.blogspot.com/feeds/3579004464988468458/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18135354&amp;postID=3579004464988468458' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18135354/posts/default/3579004464988468458'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18135354/posts/default/3579004464988468458'/><link rel='alternate' type='text/html' href='http://victorpoluceno.blogspot.com/2008/09/python-e-mvc-parte-1.html' title='Python e MVC - Parte 1'/><author><name>Victor Godoy Poluceno</name><uri>http://www.blogger.com/profile/17775902426597865021</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-x0AJ0RNWXI4/TgTOYCzjEFI/AAAAAAAAABA/l5rWzOjef7Q/s220/avatar.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18135354.post-8979732809612653636</id><published>2008-09-04T14:58:00.010-03:00</published><updated>2008-09-19T16:08:45.559-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='django'/><category scheme='http://www.blogger.com/atom/ns#' term='web2.0'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Django 1.0</title><content type='html'>Depois de uma espera de três anos finalmente foi &lt;a href="http://www.djangoproject.com/weblog/2008/sep/03/1/"&gt;lançada a versão 1.0&lt;/a&gt; do excelente framework web &lt;a href="http://www.djangoproject.com/"&gt;Django&lt;/a&gt;. O lançamento dessa versão representa muito para esse framework que se tornou o mais popular framework web escrito em Python.&lt;br /&gt;&lt;br /&gt;A versão 1.0 traz consigo um número muito grande de vantagens para os desenvolvedores, mas a principal é a estabilidade. Com toda certeza essa versão deve definitivamente posicionar esse excelente trabalho da comunidade como uma das melhores escolhas para desenvolvimento web.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://docs.djangoproject.com/en/dev/releases/1.0/"&gt;Confira todas as novidades!&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.djangoproject.com/download/"&gt;Experimente essa excelente ferramenta!&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Parabéns a toda comunidade.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18135354-8979732809612653636?l=victorpoluceno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://victorpoluceno.blogspot.com/feeds/8979732809612653636/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18135354&amp;postID=8979732809612653636' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18135354/posts/default/8979732809612653636'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18135354/posts/default/8979732809612653636'/><link rel='alternate' type='text/html' href='http://victorpoluceno.blogspot.com/2008/09/django-10.html' title='Django 1.0'/><author><name>Victor Godoy Poluceno</name><uri>http://www.blogger.com/profile/17775902426597865021</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-x0AJ0RNWXI4/TgTOYCzjEFI/AAAAAAAAABA/l5rWzOjef7Q/s220/avatar.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18135354.post-558181434430357419</id><published>2008-08-14T11:07:00.018-03:00</published><updated>2008-08-14T14:42:31.798-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='generators'/><category scheme='http://www.blogger.com/atom/ns#' term='recursivo'/><category scheme='http://www.blogger.com/atom/ns#' term='fibonacci'/><category scheme='http://www.blogger.com/atom/ns#' term='phi'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='funcional'/><title type='text'>Implementações da Sequência de Fibonacci em Python</title><content type='html'>O número de Fibonacci [1] ou sequência de Fibonacci é um exemplo clássico utilizado na computação para demonstração de recursividade.&lt;br /&gt;&lt;br /&gt;No entanto, existem diversas implementações e geralmente com uma performance melhor que a versão recursiva:&lt;br /&gt;&lt;br /&gt;Versão recursiva:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def fibonacci(n):&lt;br /&gt;    if n &lt; 2:&lt;br /&gt;        return n&lt;br /&gt;    else:&lt;br /&gt;        return fibonacci(n-1)+fibonacci(n-2)&lt;br /&gt;&lt;br /&gt;for x in range(10):&lt;br /&gt;    fibonacci(x)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Versão iterativa:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def fibonacci(n):&lt;br /&gt;    a,b = 0,1&lt;br /&gt;    for i in range(n):&lt;br /&gt;        a,b = b,a+b&lt;br /&gt;    return a&lt;br /&gt;&lt;br /&gt;for x in range(10):&lt;br /&gt;    fibonacci(x)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Versão iterativa com "generators" [3]:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def fibonacci():&lt;br /&gt;    a, b = 0, 1&lt;br /&gt;    while True:&lt;br /&gt;       yield a&lt;br /&gt;       a,b = b,a+b&lt;br /&gt;&lt;br /&gt;f = fibonacci3()&lt;br /&gt;for x in range(10):&lt;br /&gt;    f.next()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Versão com "cálculo da proporção áurea (phi)" [4]&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;from math import log&lt;br /&gt;phi = (1 + 5**0.5) / 2&lt;br /&gt;&lt;br /&gt;def fibonacci(n):&lt;br /&gt;    return int(round((phi**n - (1-phi)**n) / 5**0.5))&lt;br /&gt;&lt;br /&gt;for x in range(10):&lt;br /&gt;    fibonacci(x)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Versão recursiva/funcional:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;fibonacci = lambda n,a=1,b=1:[b,0][n&gt;0] or fibonacci(n-1,b,a+b)&lt;br /&gt;&lt;br /&gt;for x in range(10):&lt;br /&gt;    fibonacci(x)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Utilizando o módulo "timeit" [5] repetindo 3 vezes e executando 1000 vezes cada função temos a lista de performance:&lt;br /&gt;&lt;br /&gt;Versão recursiva: 0.635288953781&lt;br /&gt;Versão iterativa: 0.0393660068512&lt;br /&gt;Versão iterativa com "generators": 0.0163049697876&lt;br /&gt;Versão com "cálculo da proporção áurea (phi)": 0.0362870693207&lt;br /&gt;Versão recursiva/funcional: 0.100222110748&lt;br /&gt;&lt;br /&gt;De longe o pior resultado é a versão recursiva como esperado, e o melhor resultado é da versão iterativa com "generators". &lt;br /&gt;&lt;br /&gt;[1] - http://en.wikipedia.org/wiki/Fibonacci_number&lt;br /&gt;[2] - http://pt.wikipedia.org/wiki/Recursividade&lt;br /&gt;[3] - http://www.python.org/dev/peps/pep-0255/&lt;br /&gt;[4] - http://en.wikipedia.org/wiki/Golden_ratio&lt;br /&gt;[5] - http://docs.python.org/lib/module-timeit.html&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18135354-558181434430357419?l=victorpoluceno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://victorpoluceno.blogspot.com/feeds/558181434430357419/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18135354&amp;postID=558181434430357419' title='3 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18135354/posts/default/558181434430357419'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18135354/posts/default/558181434430357419'/><link rel='alternate' type='text/html' href='http://victorpoluceno.blogspot.com/2008/08/implementaes-da-sequncia-de-fibonacci.html' title='Implementações da Sequência de Fibonacci em Python'/><author><name>Victor Godoy Poluceno</name><uri>http://www.blogger.com/profile/17775902426597865021</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-x0AJ0RNWXI4/TgTOYCzjEFI/AAAAAAAAABA/l5rWzOjef7Q/s220/avatar.png'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18135354.post-1683585686773798552</id><published>2008-03-07T10:18:00.005-03:00</published><updated>2008-08-11T08:27:17.958-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='private_key'/><category scheme='http://www.blogger.com/atom/ns#' term='socket'/><category scheme='http://www.blogger.com/atom/ns#' term='ssl'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='cert'/><category scheme='http://www.blogger.com/atom/ns#' term='pkcs23'/><title type='text'>Python + SSL + Certificado digital</title><content type='html'>É comum durante o desenvolvimento de um programa que este precise de comunicação com serviços de terceiros disponíveis na rede.&lt;br /&gt;&lt;br /&gt;Em &lt;span style="font-weight:bold;"&gt;Python&lt;/span&gt; como em outras linguagens, todo meio de comunicação via rede utiliza basicamente &lt;span style="font-weight:bold;"&gt;socket&lt;/span&gt; em seu nível mais baixo para prover essa comunicação, seja o meio de comunicação SOAP, rpc, http, etc. &lt;br /&gt;&lt;br /&gt;Algumas vezes estes serviços externos fornecem a possibilidade de utilização de canais seguros para comunicação &lt;span style="font-weight:bold;"&gt;(ssl)&lt;/span&gt;. Em alguns casos o serviço a ser utilizado pode até mesmo obrigar o uso de comunicação segura, para isso precisamos utilizar &lt;span style="font-weight:bold;"&gt;socket + ssl&lt;/span&gt;. Dependendo da necessidade do projeto pode ser necessário utilizar também um certificado digital juntamente com a conexão &lt;span style="font-weight:bold;"&gt;ssl&lt;/span&gt; como forma de autenticação.&lt;br /&gt;&lt;br /&gt;Para utilizar comunicação segura o módulo &lt;a href="http://docs.python.org/lib/module-socket.html"&gt;'socket'&lt;/a&gt; prove a função &lt;span style="font-weight:bold;"&gt;'ssl'&lt;/span&gt;, que de maneira simples executa a comunicação com o serviço desejado via &lt;span style="font-weight:bold;"&gt;ssl&lt;/span&gt;. Essa função também pode receber dois parâmetros , 'key_file' e 'cert_file' respectivamente o 'path' do arquivo PEM para a chave privada e o 'path' para o arquivo PEM do certificado.&lt;br /&gt;&lt;br /&gt;Uma assinatura digital geralmente é um arquivo binário no formato 'pkcs12' com a extensão '.pfx', sendo assim precisamos abrir esse arquivo e retirar as duas informações que o 'ssl' precisa &lt;span style="font-weight:bold;"&gt;(key_file, cer_file)&lt;/span&gt; e salvar nos arquivos com o formato PEM. Para isso utilizamos &lt;a href="http://www.openssl.org/"&gt;openssl&lt;/a&gt; e &lt;a href="http://pyopenssl.sourceforge.net/"&gt;pyopenssl&lt;/a&gt;, &lt;span style="font-weight:bold;"&gt;'bindings'&lt;/span&gt; para python da 'lib' 'openssl'.&lt;br /&gt;&lt;br /&gt;Com os módulos instalados, vamos abrir o certificado no formato binário, transformar no objeto 'pkcs12' e então retirar as informações do certificado e da chave privada para em seguida salvar cada um em arquivo separado.&lt;br /&gt;&lt;br /&gt;Alguns certificados podem estar codificados sendo necessário informar a frase para decodificação, para tal temos o parâmetro 'passphrase', se não for preciso é só não informar o parâmetro como no exemplo abaixo.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;from OpenSSL import crypto&lt;br /&gt;&lt;br /&gt;# Lendo o arquivo pfx no formato pkcs12 como binario&lt;br /&gt;pkcs12 = crypto.load_pkcs12(open('certificado.pfx', 'rb').read(), 'passphrase')&lt;br /&gt;&lt;br /&gt;# Retorna a string decodificado do certificado &lt;br /&gt;cert_str = crypto.dump_certificate(crypto.FILETYPE_PEM, pkcs12.get_certificate())&lt;br /&gt;&lt;br /&gt;# Retorna a string decodificado da chave privada&lt;br /&gt;key_str = crypto.dump_privatekey(crypto.FILETYPE_PEM, pkcs12.get_privatekey())&lt;br /&gt;&lt;br /&gt;# Gravando a string no dicso &lt;br /&gt;open('cert.pem', 'wb').write(cert_str)&lt;br /&gt;&lt;br /&gt;# Gravando a string no dicso &lt;br /&gt;open('key.ptm', 'wb').write(key_str)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Agora para finalizar basta efetuar a comunicação com o serviço desejado utilizando o modulo 'socket' e a função 'ssl' passando os parâmetros de chave e certificado:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;proxy = socket.socket(socket.AF_INET, socket.SOCK_STREAM)&lt;br /&gt;proxy.connect(('www.lzt.com.br', 80))&lt;br /&gt;proxy_ssl = socket.ssl(proxy, 'key.pem', 'cert.pem')&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Pronto! Com o objeto 'proxy' podemos fazer requisições a serviços que utilizem conexão 'ssl' com certificados digitais.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18135354-1683585686773798552?l=victorpoluceno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://victorpoluceno.blogspot.com/feeds/1683585686773798552/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18135354&amp;postID=1683585686773798552' title='6 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18135354/posts/default/1683585686773798552'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18135354/posts/default/1683585686773798552'/><link rel='alternate' type='text/html' href='http://victorpoluceno.blogspot.com/2008/03/python-ssl-certificado-digital.html' title='Python + SSL + Certificado digital'/><author><name>Victor Godoy Poluceno</name><uri>http://www.blogger.com/profile/17775902426597865021</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-x0AJ0RNWXI4/TgTOYCzjEFI/AAAAAAAAABA/l5rWzOjef7Q/s220/avatar.png'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18135354.post-7943498312680031582</id><published>2007-02-27T13:08:00.001-03:00</published><updated>2008-08-11T08:32:08.795-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ctypes'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Links para o ctypes</title><content type='html'>Estou dando uma olha no ctypes, vou utilzar aqui na empresa então estou reunindo alguns &lt;a href="http://del.icio.us/victorpoluceno/ctypes"&gt;links&lt;/a&gt; sobre o assunto.&lt;br /&gt;&lt;br /&gt;Pretendo escrever um tutorial sobre o ctypes, assim que estiver legal posto aqui.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18135354-7943498312680031582?l=victorpoluceno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://victorpoluceno.blogspot.com/feeds/7943498312680031582/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18135354&amp;postID=7943498312680031582' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18135354/posts/default/7943498312680031582'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18135354/posts/default/7943498312680031582'/><link rel='alternate' type='text/html' href='http://victorpoluceno.blogspot.com/2007/02/links-para-o-ctypes.html' title='Links para o ctypes'/><author><name>Victor Godoy Poluceno</name><uri>http://www.blogger.com/profile/17775902426597865021</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-x0AJ0RNWXI4/TgTOYCzjEFI/AAAAAAAAABA/l5rWzOjef7Q/s220/avatar.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18135354.post-3064690051792588862</id><published>2007-02-21T18:47:00.001-02:00</published><updated>2008-08-11T08:31:45.147-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='pypy'/><title type='text'>PyPy - nova versão do projeto</title><content type='html'>Acaba de sair do forno a versão 0.99.0 do projeto PyPy. IMVHO um dos mais promissores e revolucionários projetos relacionados a Python da atualidade. &lt;br /&gt;&lt;br /&gt;Bom, juntei alguns &lt;a href="http://del.icio.us/victorpoluceno/pypy"&gt;links&lt;/a&gt; sobre PyPy. Estou muito impressionado com o projeto e comecei a estudar o modelo de funcionamento dele, assim que tiver algo concreto postarei aqui.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18135354-3064690051792588862?l=victorpoluceno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://victorpoluceno.blogspot.com/feeds/3064690051792588862/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18135354&amp;postID=3064690051792588862' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18135354/posts/default/3064690051792588862'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18135354/posts/default/3064690051792588862'/><link rel='alternate' type='text/html' href='http://victorpoluceno.blogspot.com/2007/02/pypy-nova-verso-do-projeto.html' title='PyPy - nova versão do projeto'/><author><name>Victor Godoy Poluceno</name><uri>http://www.blogger.com/profile/17775902426597865021</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-x0AJ0RNWXI4/TgTOYCzjEFI/AAAAAAAAABA/l5rWzOjef7Q/s220/avatar.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18135354.post-1413032385162810790</id><published>2007-02-06T13:08:00.001-02:00</published><updated>2008-08-11T08:28:24.567-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='sort'/><category scheme='http://www.blogger.com/atom/ns#' term='python2.3'/><title type='text'>Ordenando listas no python2.3 e inferiores</title><content type='html'>&lt;span style="font-weight:bold;"&gt;Ordenação simples&lt;/span&gt;&lt;br&gt;&lt;br /&gt;Um objeto to tipo 'list' possui um método chamado 'sort' que faz a ordenação 'in-place' (resultado na própria variável) do objeto.&lt;br&gt;&lt;br /&gt;Descrição do método:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;L.sort([cmpfunc]) -- sort *IN PLACE*; if given, cmpfunc(x, y) -&gt; -1, 0, 1'&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Exemplo:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; lista = ['a', 'c', 'b']&lt;br /&gt;&gt;&gt;&gt; lista.sort()&lt;br /&gt;&gt;&gt;&gt; lista&lt;br /&gt;['a', 'b', 'c']&lt;br /&gt;&gt;&gt;&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;&lt;br /&gt;Ordenação simples inversa&lt;/span&gt;&lt;br&gt;&lt;br /&gt;Para ordenar uma lista do maior para o menor item temos o método 'reverse', que trabalha de maneira análoga ao método 'sort'.&lt;br&gt;&lt;br /&gt;Exemplo:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; lista.reverse()&lt;br /&gt;&gt;&gt;&gt; lista&lt;br /&gt;['c', 'b', 'a']&lt;br /&gt;&gt;&gt;&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Ordenação de lista de dicionários por uma chave&lt;/span&gt;&lt;br&gt;&lt;br /&gt;O metodo 'sort' aceita uma função de comparação como paramêtro. Essa função caso seja informada será utilizada para comparar os itens da lista e resolver qual item prioridade na ordem sobre os demais.&lt;br /&gt;&lt;br /&gt;Para que o método ordene a lista se baseando na chave dos dicionários a função criada sobrescreve a função 'bulti-in' 'cmp' do python.&lt;br /&gt;&lt;br /&gt;A função 'cmp' como podemos ver abaixo, compara dois objetos recebidos como paramêtro retornando um inteiro que informa qual dos itens é maior ou se os dois são iguais. Baseado no resultado da função 'cmp' a função 'sort' ira ordenar a lista.&lt;br /&gt;&lt;br /&gt;Descrição do método:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;'cmp(x, y) -&gt; integer\n\nReturn negative if x&lt;y, x="="y,"&gt;y.'&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Em nosso exemplo desejamos ordenar a lista utilizando como base a chave (coluna) '2' do dicionário e assim a definimos. &lt;br /&gt;&lt;br /&gt;Quando a função 'sort' estiver interando sobre a lista, ela vai passar cada item encontrado para a nossa função sort modificada 'mycmp' que por sua vez irá chamar a funcao 'cmp' passando como paramêtro o valor das chaves no dicionário pelo qual desejamos ordenar.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; lista = [{1: 'b', '2': 'b'}, {1: 'c', '2': 'a'}]&lt;br /&gt;&gt;&gt;&gt;&lt;br /&gt;... def mycmp(a, b):&lt;br /&gt;...      print a&lt;br /&gt;...      print b&lt;br /&gt;...      return cmp(a.get('2'), b.get('2'))&lt;br /&gt;...&lt;br /&gt;&gt;&gt;&gt; lista.sort(mycmp)&lt;br /&gt;&gt;&gt;&gt; lista&lt;br /&gt;[{1: 'b', '2': 'b'}, {1: 'c', '2': 'a'}]&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Também podemos utilizar 'lambda' para criar uma função anônima. O resultado é o mesmo, talvez com alguma variação de performance.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;lista.sort(lambda x,y: cmp(a.get('2'), b('2')))&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Ordenar listas de dicionários de acordo com uma ou mais chaves escolhidas&lt;/span&gt;&lt;br&gt;&lt;br /&gt;A função abaixo recebe dois paramêtros, a lista que se deseja ordenar e a lista de chaves que devem ditar a ordenação. &lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; lista = [{1: 1, '2': 'b', '3': 0}, {1: 1, '2': 'a', '3': -1}, {1: 0, '2': 'd', '3': 5}]&lt;br /&gt;&gt;&gt;&gt; def sort_list(l, sort_keys):&lt;br /&gt;...         def mycmp(a, b):&lt;br /&gt;...                k1 = map(lambda x: a.get(x), sort_keys)&lt;br /&gt;...                 k2 = map(lambda x: b.get(x), sort_keys)&lt;br /&gt;...                return cmp(k1, k2)&lt;br /&gt;...&lt;br /&gt;...         l.sort(mycmp)&lt;br /&gt;...        return l&lt;br /&gt;...&lt;br /&gt;&gt;&gt;&gt; sort_list('1', lista, ['2', '1'])&lt;br /&gt;[{1: 1, '3': -1, '2': 'a'}, {1: 1, '3': 0, '2': 'b'}, {1: 0, '3': 5, '2': 'd'}]&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Criamos uma função 'closure' chamada 'mycmp', que como no exemplo anterior será passada para a função 'sort'. Dentro da funcao 'mycmp' é onde temos a diferença básica em relacao a função anterior. Ao invés de dizer qual o resultado de cada dicionário que ele deve utilizar para ordenar, passamos duas listas com os valores das colunas pelas quais desejamos ordenar.&lt;br /&gt;&lt;br /&gt;Novamente, o 'sort' utlizando a funcao 'cmp' irá decidir qual dos dois objetos deve ter a preferência e assim ordenar a lista de dicionários de acordo com as colunas que especificamos.&lt;br /&gt;&lt;br /&gt;Atenção, alguns módulos como por exemplo 'mxDatetime' sobrescrevem o método sort para que funcionem a seu gosto. Isso pode fazer com o que o método 'cmp' que estiver no namespace local não seja o 'cmp' original, caso você utilize algum módulo onde isso acontece o sort não irá funcionar corretamente. Neste caso deveremos importar a função 'cmp' diretamente das funções 'bulti-in' ou melhor do namespace '__builtin__'.&lt;br&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Detalhe sobre a implementação do método sort&lt;/span&gt;&lt;br&gt;&lt;br /&gt;O algoritmo de 'sort' utilizado no python é um tando diferente dos algoritmos tradicionais, um tipo de mergesort com algumas coisas a mais.&lt;br&gt;&lt;br /&gt;Retirado dos fontes do python listsort.txt:&lt;br&gt;&lt;br /&gt;"&lt;span style="font-style:italic;"&gt;This describes an adaptive, stable, natural mergesort, modestly called timsort (hey, I earned it &lt;wink&gt;).  It has supernatural performance on many kinds of partially ordered arrays (less than lg(N!) comparisons needed, and as few as N-1), yet as fast as Python's previous highly tuned samplesort hybrid on random arrays.&lt;br /&gt;&lt;br /&gt;In a nutshell, the main routine marches over the array once, left to right, alternately identifying the next run, then merging it into the previous runs "intelligently".  Everything else is complication for speed, and some hard-won measure of memory efficiency.&lt;/span&gt;"&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18135354-1413032385162810790?l=victorpoluceno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://victorpoluceno.blogspot.com/feeds/1413032385162810790/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18135354&amp;postID=1413032385162810790' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18135354/posts/default/1413032385162810790'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18135354/posts/default/1413032385162810790'/><link rel='alternate' type='text/html' href='http://victorpoluceno.blogspot.com/2007/02/ordenando-listas-no-python23-e.html' title='Ordenando listas no python2.3 e inferiores'/><author><name>Victor Godoy Poluceno</name><uri>http://www.blogger.com/profile/17775902426597865021</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-x0AJ0RNWXI4/TgTOYCzjEFI/AAAAAAAAABA/l5rWzOjef7Q/s220/avatar.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18135354.post-115383951003658833</id><published>2006-07-25T09:55:00.001-03:00</published><updated>2008-08-11T08:31:07.721-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='pdb'/><title type='text'>Debugando Python com pdb</title><content type='html'>Programar sem alguma ferramenta para debug pode ser um grande sofrimento.&lt;br /&gt;&lt;br /&gt;Poucas pessoas conhecem ou utilizam, mas o Python, possui um módulo de debug incorparado a biblioteca padrão, chamado &lt;a href="http://www.python.org/doc/current/lib/module-pdb.html"&gt;pdb&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;"The module &lt;/span&gt;&lt;tt style="font-style: italic;" class="module"&gt;pdb&lt;/tt&gt;&lt;span style="font-style: italic;"&gt; defines an interactive source code debugger for Python programs.  It supports setting (conditional) breakpoints and single stepping at the source line level, inspection of stack frames, source code listing, and evaluation of arbitrary Python code in the context of any stack frame.  It also supports post-mortem debugging and can be called under program control."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;E para alegria de muitos programadores ele cumpre bem o que promete.&lt;br /&gt;&lt;br /&gt;Uso básico:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import pdb; pdb.set_trace()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Quando a linha acima for executadao, o pdb toma conta da situação e seu prompt fica disponivel para que o programador possa debugar seu programa da maneria mais tradicional possivel, o '&lt;span style="font-weight: bold;"&gt;set_trace&lt;/span&gt;'  é um ponto de rastreamento ou captura que colocamos em nosso código.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;-&gt; Pdb().set_trace()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;(Pdb)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Aqui fica intuitivo os comandos são simples &lt;span style="font-weight: bold;"&gt;'n - next'&lt;/span&gt;, &lt;span style="font-weight: bold;"&gt;'c - continue'&lt;/span&gt; e assim por diante. Para mais detalhes '&lt;span style="font-weight: bold;"&gt;help'.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;O inconveniente deste processo é que temos que modificar nossos fontes para poder debugar, adicionando a linha de captura (chamada do metodo set_trace). O esquecimento desta linha no código por exemplo, pode fazer com que o programa fique travado.&lt;br /&gt;&lt;br /&gt;Para evitar essas situações podemos utilizar o pdb pela &lt;span style="font-weight: bold;"&gt;linha de comando&lt;/span&gt; no estilo do &lt;span style="font-weight: bold;"&gt;gdb&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;python -m pdb programa.py&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Deste modo o prompt vai ser invocado e então podemos dizer em qual linha será colocado o break, '&lt;span style="font-weight: bold;"&gt; b 10&lt;/span&gt;' por exemplo e depois &lt;span style="font-weight: bold;"&gt;'c&lt;/span&gt;' para rodar até o break.&lt;br /&gt;&lt;br /&gt;Infelizmente a opção &lt;span style="font-weight: bold;"&gt;'-m'&lt;/span&gt; só funciona no python 2.4, para versões mais antigas podemos executar o pdb diretamente da biblioteca informando o arquivo fonte como argumento, no meu caso:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;python /usr/local/lib/python2.2/pdb.py main.py&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Crie um link simbolico para o pdb e seja feliz.&lt;br /&gt;&lt;br /&gt;Existe ainda uma versão do pdb extendida chamada &lt;a href="http://bashdb.sourceforge.net/pydb/"&gt;pypdb,&lt;/a&gt; que me parece bastante interessante, mas também requer python &gt;= 2.4.0. O &lt;span style="font-weight: bold;"&gt;pypdb&lt;/span&gt; funciona ainda mais na linha do gdb, até mesmo sendo um programa binário externo que invoca o código python a ser debugado.&lt;br /&gt;&lt;br /&gt;Para informações mais completas:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.onlamp.com/pub/a/python/2005/09/01/debugger.html"&gt;O'Reillty - Interactive Debugging in Python&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.fabiorizzo.com/python/pdbintro/"&gt;Debugando o Python&lt;/a&gt;&lt;br /&gt;&lt;a href="http://ipython.scipy.org/doc/manual/node10.html"&gt;Using the Python debugger (&lt;tt&gt;pdb&lt;/tt&gt;)&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18135354-115383951003658833?l=victorpoluceno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://victorpoluceno.blogspot.com/feeds/115383951003658833/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18135354&amp;postID=115383951003658833' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18135354/posts/default/115383951003658833'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18135354/posts/default/115383951003658833'/><link rel='alternate' type='text/html' href='http://victorpoluceno.blogspot.com/2006/07/debugando-python-com-pdb.html' title='Debugando Python com pdb'/><author><name>Victor Godoy Poluceno</name><uri>http://www.blogger.com/profile/17775902426597865021</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-x0AJ0RNWXI4/TgTOYCzjEFI/AAAAAAAAABA/l5rWzOjef7Q/s220/avatar.png'/></author><thr:total>2</thr:total></entry></feed>
