Sam & Max » hack http://sametmax.com Du code, du cul Sat, 07 Nov 2015 10:56:13 +0000 en-US hourly 1 http://wordpress.org/?v=4.1 Apprendre le python en 10 ans… 29 http://sametmax.com/apprendre-le-python-en-10-ans/ http://sametmax.com/apprendre-le-python-en-10-ans/#comments Fri, 08 Nov 2013 06:31:12 +0000 http://sametmax.com/?p=7660 "Comment devenir un hacker ?" dans un monopolisant moteur de recherche... Comme ça... Pour déconner...]]> Ceci est un post invité de 01ivier posté sous licence creative common 3.0 unported.

Il y a quelques années, esseulé devant 1 millions de pixels noctures, j’ai tapé “Comment devenir un hacker ?” dans un monopolisant moteur de recherche…
Comme ça…
Pour déconner…

Je suis alors tombé sur le texte “Comment devenir un hacker ?” d’Eric Steven Raymond.

Après quelques instants dubitatifs où j’ai pris conscience que si j’avais écrit “Comment planter des choux ?” ou autres “Comment dessiner un poulet en contre-plongée ?” je serai certainement tombé sur un document du même nom, j’ai commencé à lire le texte en question.
Mais ce n’est que plusieurs mois après que j’en suis venu à bout.

En effet, arrivé à la partie “Apprenez à programmer”, j’ai non seulement réalisé que je ne savais pas vraiment programmer mais surtout que je pouvais dès à présent mettre à l’épreuve ma théorie sur les choux et les poulets.
J’ai donc cherché “Comment apprendre à programmer ?” et j’ai fini par tomber sur l’article “Apprendre à programmer en 10 ans ?

Celui-là, je l’ai lu en entier et d’une seule traite.
Mais le titre seulement avait suffit à me décomplexer pour deux ou trois vies.

Comment acquérir une compétence en 10 ans?

Quelle évidence !
Tout me paraissait bien plus envisageable en me donnant 10 ans pour y arriver…
Je veux apprendre l’espagnol ? Et bien je ferai le bilan dans 10 ans…
Pas besoin de culpabiliser parce que je n’ai pas fait la page du jour de la méthode à Mimile…

Il devait être 1h du matin et je me suis dit :
“Et si j’apprenais le Python…”
J’avais 10 ans devant moi, mais ce n’était pas une raison pour perdre du temps.

À 6h, j’avais donc bouclé la première partie du tuto “Apprendre le Python” du site du zéro et entamé la seconde…

Maintenant, vous vous demandez peut-être, si, trois an plus tard, je connais le Python…
Et bien je vous dirais ça dans sept ans… :-)

Hello world !

En attendant, j’ai proposé à Sam et Max de poster quelques articles de temps en temps…
Je ne suis pas du tout developpeur, mais je n’ai aucun scrupule à écrire des lignes de code… encore moins à publier ma prose de cochon…

Sachant qu’il est tout à fait possible d’obtenir des résultats enthousiasmants avec du code bancal, je me propose donc de décomplexer les débutants en publiant des articles de mauvais élève…
Nulle doute que les lecteurs avertis de S&M sauront, par leurs commentaires avisés, réhausser le niveau technique de mes posts afin de les rendre aussi instructifs que ceux déjà disponibles sur ce blog…

À bientôt…

]]>
http://sametmax.com/apprendre-le-python-en-10-ans/feed/ 29
Capturer l’affichage des prints d’un code Python 8 http://sametmax.com/capturer-laffichage-des-prints-dun-code-python/ http://sametmax.com/capturer-laffichage-des-prints-dun-code-python/#comments Sat, 29 Sep 2012 14:03:36 +0000 http://sametmax.com/?p=2343 Hier j’ai eu rencontré le travail d’une de ces fameuses personnes qui pensent que la ré-utilisabilité c’est pour les pédés, et qui font des scripts dont la moitié des infos renvoyées sont printées au milieu de blocs de code de 50 lignes, sans possibilité de les récupérer.

Heureusement, avec un petit hack, on peut capturer ce qu’affiche un autre code, et sauver le bébé, l’eau du bain, et même le canard en plastique.

Le code pour les gens pressés

J’ai enrobé l’astuce dans un context manager, ça rend l’utilisation plus simple.

import sys
from io import BytesIO
from contextlib import contextmanager
 
@contextmanager
def capture_ouput(stdout_to=None, stderr_to=None):
    try:
 
        stdout, stderr = sys.stdout, sys.stderr
        sys.stdout = c1 = stdout_to or BytesIO()
        sys.stderr = c2 = stderr_to or BytesIO()
        yield c1, c2
 
    finally:
 
        sys.stdout = stdout
        sys.stderr = stderr
 
        try:
            c1.flush()
            c1.seek(0)
        except (ValueError, IOError):
            pass
 
        try:
            c2.flush()
            c2.seek(0)
        except (ValueError, IOError):
            pass

Notez l’usage de yield.

Et ça s’utilise comme ça:

with capture_output() as stdout, stderr:
    fonction_qui_fait_que_printer_la_biatch()
 
print stdout.read() # on récupère le contenu des prints

Attention, le code n’est pas thread safe, c’est fait pour hacker un code crade, pas pour devenir une institution. Mais c’est fort pratique dans notre cas précis.

Comment ça marche ?

stdin (entrée standard), stdout (sortie standard) et stderr (sortie des erreurs) sont des file like objects, c’est à dire qu’ils implémentent l’interface d’un objet fichier: on peut les ouvrir, les lire, y écrire et les fermer avec des méthodes portant le même nom et acceptant les mêmes paramètres.

L’avantage d’avoir une interface commune, c’est qu’on peut du coup échanger un file like objet par un autre.

Par exemple on peut faire ceci:

import sys
log = open('/tmp/log', 'w')
sys.stdout = log # hop, on hijack la sortie standard
print "Hello"
log.close()

Comme print écrit dans stdout, en remplaçant stdout par un fichier, print va du coup écrire dans le fichier.

Mais ce code est fort dangereux, car il remplace stdout de manière définitive. Du coup, si du code print après, il va écrire dans le fichier, même les libs externes, car stdout est le même pour tout le monde dans le process Python courant.

Du coup, il est de bon ton de s’assurer la restauration de stdout à son état d’origine:

import sys
log = open('/tmp/log', 'w')
bak = sys.stdout # on sauvegarde l'ancien stdout
sys.stdout = log
print "Hello"
log.close()
sys.stdout = bak # on restore stdout

Comme je le disais plus haut, ceci n’est évidement pas thread safe, puisqu’entre la hijacking et la restoration de stdout, un autre thread peut faire un print.

Dans notre context manager, on utilise BytesIO() et non un fichier. BytesIO est un file like objet qui permet de récupérer un flux de bits en mémoire. Donc on fait écrire print dedans, ainsi on a tout ce qu’on affiche qui se sauvegarde en mémoire.

Bien entendu, vous pouvez créé vos propres file like objects, par exemple un objet qui affiche à l’écran ET capture la sortie. Par exemple, pour mitiger le problème de l’absence de thread safe: 99% des libs n’ont pas besoin du vrai stdout, juste d’un truc qui print.

import sys
from io import BytesIO
 
class PersistentStdout(object):
 
    old_stdout = sys.stdout
 
    def __init__(self):
        self.memory = BytesIO()
 
    def write(self, s):
        self.memory.write(s)
        self.old_stdout.write(s)
 
 
old_stdout = sys.stdout
sys.stdout = PersistentStdout()
 
print "test" # ceci est capturé et affiché
 
sys.stdout.memory.seek(0)
res = sys.stdout.memory.read()
 
sys.stdout = PersistentStdout.old_stdout
 
print res # résultat de la capture

Pour cette raison le code du context manager permet de passer le file like objet à utiliser en argument. On notera aussi que si on souhaite rediriger stdout mais pas stderr et vice-versa, il suffit de passer sys.stdout et sys.stderr en argument :-)

]]>
http://sametmax.com/capturer-laffichage-des-prints-dun-code-python/feed/ 8