Site original : Sam & Max: Python, Django, Git et du cul
Ceci est un post invité de 01ivier posté sous licence creative common 3.0 unported.
L’un des premiers “vrais” scripts que j’ai écrit en Python avait pour fonction de flooder une boite mail…
Pas très sympathique à première vue, mais c’est sans compter le fait que j’ai pris ma carte au club des gentils depuis plusieurs années…
Je floode donc dans la joie et la bonne humeur.
Tout d’abord, il m’a fallu identifier un moyen pas trop compliqué d’envoyer un mail.
J’ai donc récupéré un bout de code je ne sais où et j’ai viré tout ce qui dépassait :
# -*- coding: utf-8 -*- import smtplib from email.MIMEText import MIMEText de_qui = 'ton@adresse.mail' a_qui = 'son@adresse.mail' ton_server_smtp = 'smtp.ton.FAI' message = MIMEText('Ceci est le corps du mail') message['Subject'] = 'Ceci est le titre du mail' server = smtplib.SMTP(ton_server_smtp) server.sendmail(de_qui, a_qui, message.as_string()) server.quit() print ("Le message a été envoyé avec un succès phénoménal !")
On reconnaît tout de suite le style qui caractérise les champions: pas de fonction, tout en ligne droite !
J’aimerai pouvoir vous dire ce qu’est MIMEText, mais ayant pu me débrouiller jusqu’ici sans le savoir… et bien je ne le sais pas. (Et ne comptez pas sur moi pour aller le chercher juste pour vous. J’ai une posture de mauvais élève à assumer.)
À ce niveau, sur ma Linux Mint, il me suffit de renseigner de_qui, a_qui et ton_server_smtp puis d’ouvrir un terminal là où se trouve mon script et de taper :
python go.py
(Oui, j’appelle souvent mes fichiers go.py. Comme ça j’ai l’impression qu’ils vont partir plus vite. Essayez, vous verrez. On y croit vraiment. Il faut juste s’habituer à appuyer un peu plus fort que d’habitude sur “entrer” tout en hurlant “GO !”. Mais l’effet est garanti.)
Si le message a bien “été envoyé avec un succès phénoménal” alors, quelque part dans l’univers, une boite mail a reçu un petit courrier ayant pour titre “Ceci est le titre du mail” et pour contenu “Ceci est le corps du mail”.
Je vous assure que je ne suis jamais aussi heureux de m’envoyer un mail que de cette façon.
Parfois je change l’objet pour me faire une surprise et je suis content.
Ça marche à chaque fois.
Maintenant que je savais envoyer un mail, il me fallait trouver un moyen de convertir la photo d’un petit chien en ASCII-art (rapport à la joie et la bonne humeur du flood, souvenez-vous).
J’ai trouvé mon bonheur avec le projet AA.
sudo apt-get install python-aalib
Paf !
J’ai récupéré ici un bout de code dont j’ai compris juste l’essentiel (où changer l’image, la largeur et la hauteur) et mon style tout en finesse a fait le reste :
import aalib import Image pix = 'toutou.jpg' nb_lettre_largeur = 80 nb_lettre_hauteur = 40 screen = aalib.AsciiScreen(width = nb_lettre_largeur, height = nb_lettre_hauteur) image = Image.open(pix).convert('L').resize(screen.virtual_size) screen.put_image((0, 0), image) print (screen.render())
“GO ! GO !”
python gogo.py
Ici aussi, une joie authentique est au rendez vous à chaque tentative.
C’est merveilleux.
Je savais comment envoyer un mail.
Je savais comment convertir une photo de petit chien en ASCII.
La suite découlait de source.
Il me fallait désormais unifier le tout pour pouvoir envoyer des dizaines de mails à la même adresse de manière à ce que la photo du petit chien apparaissent dans le client de messagerie de mon destinataire grâce à l’empilement des titres des messages en partant du principe qu’il utiliserai une police à chasse fixe pour l’affichage.
Tout ce qu’il y a de plus classique.
À l’époque, sur gMail, le thème “Terminal” proposait une police monospaced verte sur fond noir du plus bel effet.
Mais ce n’est plus le cas.
Heureusement, en plagiant l’interface de gMail, Yahoo a aussi plagié le thème “Terminal” avec la police qui nous intéresse.
Voici donc le petit chien que je me suis envoyé sur un compte créé pour l’occasion.
Ne me dites pas que ça ne vous donne pas envie de chialer.
Voici le script auquel j’ai (empiriquement) fini par arriver pour obtenir ce résultat émouvant :
# -*- coding: utf-8 -*- # la lib smtp qui nous permet de dialoguer avec un serveur de mail import smtplib # pour simuler une irrégularité dans l'envoi from time import sleep from random import random # nécessaire pour l'ASCII-Art import aalib import Image import sys from email.MIMEText import MIMEText de_qui = 'À RENSEIGNER' a_qui = 'À RENSEIGNER' serveur_smtp = 'À RENSEIGNER' i = j = 25 # nombre de mail a envoyer donc de ligne, nb = 81 # nombre de caractères par ligne, correspond au nombre de caractères # affichés par Yahoo pour un titre avec le skin "terminal" ############### ## FONCTIONS ## ############### def gotoascii(pix): screen = aalib.AsciiScreen(width = nb-1, height = j) image = Image.open(pix).convert('L').resize(screen.virtual_size) screen.put_image((0, 0), image) # les replace() concernent des caractères qui sont gérés différemment # des autres quand ils sont utilisés dans le tite d'un mail. return (screen.render().replace(' ', '.').replace(',', '.').replace(';','.')) def essai(pix): # permet éventuellement de tester le rendu de l'image avant de l'envoyer print (gotoascii(pix)) def ligne(num_l, pix): # Comme il y a 'nb' élément par ligne, on compte de 'nb' en 'nb' # en fonction du numéro de la ligne renseigné par 'num_l' return (gotoascii(pix)[nb*num_l:nb*(num_l+1)]) def send(num, pix): email = MIMEText("Qu'est-ce qu'on s'amuse !") # L'objet du mail est la ligne donnée en premier argument # de l'image ASCII donnée en deuxième argument email['Subject'] = ligne(num, pix) server = smtplib.SMTP(serveur_smtp) server.sendmail(de_qui, a_qui, email.as_string()) server.quit() ######################### ## PROGRAMME PRINCIPAL ## ######################### # Écoute le flag -test pour faire... des tests # --> python go.py -test monImage.jpg if sys.argv[1] == "-test": essai(sys.argv[2]) else: while i > 0: # Augmente le délais et brise la régularité des envois de mail # afin d'éviter, peut-être, d'être black-listé par Yahoo :-p # Utilité purement hypothétique. sleep(20*random()+10) # Envoi le mail send(i-1, sys.argv[1]) if i == 1: print ("Mail n°{0} envoyé. Il n'en reste plus.".format(j+1-i)) else: print ("Mail n°{0} envoyé. Il en reste encore {1}.".format(j+1-i, i-1)) i -= 1 print ("Bravo ! Cet envoi a été un succès !")
Pour l’utiliser, j’ai fait en sorte de pouvoir passer l’image à envoyer en argument.
python go.py monImage.jpg
J’ai écrit ce script il y a un peu plus de 2 ans, et, même si je progresse lentement, je me rends bien compte désormais, que je recalcule l’image à chaque mail .
Mais je vous l’ai laissé en l’état, car c’est tout aussi attendrissant qu’un chiot, je trouve.
Surtout qu’à part ça, le reste frôle la perfection (la gestion des arguments doit en laisser plus d’un rêveur, j’imagine).
Enfin, grâce à Sam & Max, j’ai découvert qu’il était possible d’utiliser d’autres photos que celle du petit chien.
Merci à eux.
Automatiser le déploiement d’un projet Django passe par un syncdb
sans prompt, et donc pas de création de superutilisateur :
./manage.py syncdb --noinput
Vous pouvez bien entendu toujours en créer un plus tard, avec :
./manage.py createsuperuser --username=vous --email=votre_mail
Mais il va vous prompter pour saisir le mot de passe ou alors mettre un mot de passe inutilisable automatiquement, ça ne résout pas votre problème. Une astuce consiste à le créer avec un code Python et à piper ce code dans un shell :
echo "from django.contrib.auth.models import User; User.objects.filter(username='vous').count() or User.objects.create_superuser('vous', votre_email', 'mot_de_passe')" | ./manage.py shell
Personnellement je colle ça dans une tache fabric. Parfois on peut même générer le mot de passe aléatoirement avec un uuid qui est printé localement.
Vous êtes dans une situation où vous ne pouvez pas utiliser uniquement une clé pour vous authentifier, et il faut taper votre putain de mot de passe à chaque push.
Ça sent le vécu n’est-ce pas ?
Mais bien entendu git vient avec une option bien cachée au fond de son fion pour adresser ce problème :
git config credential.helper 'cache --timeout=3600'
Et votre authentification sera gardée en mémoire pour une heure. Vous pouvez faire :
git config --global credential.helper 'cache --timeout=3600'
Pour l’étendre à tous les repos de votre machine.
Ceci est un post invité de Toniob posté sous licence creative common 3.0 unported.
Oh oui, je sais ce que vous allez me dire, et vous avez parfaitement raison. Oui, il m’arrive d’être un peu obtus sur certaines choses, surtout quand il s’agit d’un domaine que je connais. Bref, aujourd’hui nous allons parler de ifconfig et de route.
Soyons clair tout de suite : arrêtez d’utiliser ces merdes, elles sont dépréciées depuis longtemps ! Je sais comment sont les informaticiens de manière générale, et les administrateurs systèmes en particulier. Il est difficile de changer leurs habitudes. Mais si on vous proposait Scarlett Johansson, vous resteriez fidèle à Régine ou Jonathan Rhys Meyers si vous aviez Mickey Rourke ? Je vois à vos yeux lubriques que vous m’avez saisi. Alors c’est parti.
Les interfaces
Utilisez la commande ip, c’est un ordre. Elle remplacera avantageusement ifconfig. Dans la suite de ce billet, je mettrai des exemples de commandes avec ifconfig et leur équivalent avec ip. Commençons avec du simple, afficher la liste des interfaces disponibles :
# ifconfig -a
eth0 Link encap:Ethernet HWaddr 00:90:f5:ee:62:31
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 lg file transmission:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Interruption:20 Mémoire:f7e00000-f7e20000
lo Link encap:Boucle locale
inet adr:127.0.0.1 Masque:255.0.0.0
adr inet6: ::1/128 Scope:Hôte
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:12 errors:0 dropped:0 overruns:0 frame:0
TX packets:12 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 lg file transmission:0
RX bytes:720 (720.0 B) TX bytes:720 (720.0 B)
$ ip addr
1: lo:
Vous voyez, pour le moment ce n’est pas si compliqué, vous économisez même de précieuses lettres. Vous constatez que la sortie est différente, mais vous y trouverez globalement les mêmes informations. C’est une question d’habitude. Personnellement, ça m’a pris un peu de temps, mais je ne reviendrais en arrière pour rien au monde.
On va maintenant assigner une adresse ip. Bon, j’avoue, c’est un peu plus long cette fois avec la commande ip :
# ifconfig eth0 192.168.1.1/24
# ip addr add 192.168.1.1/24 dev eth0
Et si maintenant nous ajoutions une adresse ipv4 ? Sauf qu’avec ifconfig, ce n’est pas possible, on ne peut le faire qu’avec ip :
# ip addr add 192.168.1.2/32 dev eth0
Si on affiche la configuration de l’interface réseau :
# ifconfig eth0
eth0 Link encap:Ethernet HWaddr 00:90:f5:ee:62:31
inet adr:192.168.1.1 Bcast:0.0.0.0 Masque:255.255.255.0
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 lg file transmission:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Interruption:20 Mémoire:f7e00000-f7e20000
$ ip addr show eth0
2: eth0:
Et oui, rien du côté de ifconfig. Il ne voit pas que l’interface dispose de deux adresses différentes. Alors qu’il fallait utiliser des alias d’interface avec ifconfig, plus de souci de ce côté là avec ip. Voici maintenant quelques exemples d’autres commandes pouvant être utiles :
# ifconfig eth0 mtu 9000
# ip link set eth0 mtu 9000
# ifconfig eth0 up
# ip link set eth0 up
Les routes
Passons maintenant aux routes. Si vous utilisez ifconfig, vous vous servez aussi probablement de route. C’est fini les conneries maintenant ! Commençons par les afficher :
# route -n
Table de routage IP du noyau
Destination Passerelle Genmask Indic Metric Ref Use Iface
192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
$ ip route
192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.1
Oui, la sortie est moins verbeuse par défaut. Ça devrait vous plaire pour vos scripts shell. Ajoutons maintenant une route par défaut :
# route add default gw 192.168.1.254
# ip route add defaut via 192.168.1.254
Et si on regarde le résultat de la commande ip route maintenant :
$ ip route
default via 192.168.1.254 dev eth0
192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.1
Contrairement à route, ip route génère une sortie qui peut être copiée / collée dans un ip route add. Pratique pour dupliquer une conf sur un autre serveur. Pour ajouter une route vers un hôte ou un réseau en particulier :
# route add -net 192.168.2.0 netmask 255.255.255.0 gw 192.168.1.253
# ip route add 192.168.2.0/24 via 192.168.1.253
C’est une affaire de goût, mais je préfère largement la syntaxe de ip à celle de route.
Conclusion
Voilà cette petite introduction à la commande ip est terminée. Essayez de remplacer ifconfig dans vos usages au quotidien. Ça prend un peu de temps pour s’y faire, mais la syntaxe plus claire et les fonctionnalités disponibles permettent vite d’être plus rapide dans la configuration réseau d’une machine. Les exemples que j’ai donnés dans cet article devraient être suffisants pour 90% des usages. Si vous cherchez à vouloir en faire plus, il suffit d’ajouter l’option help à votre ligne de commande pour avoir des informations. Plus pratique que d’avoir à taper dans le man sans arrêt.
Si cet article vous plaît (merci de me faire des commentaires élogieux, c’est mon premier ici), j’essaierai de vous faire découvrir un peu plus la stack réseau sous Linux. Si les vlans sont connus, les bondings un peu moins, je pense que les macvtaps sont un mystère pour la plupart d’entre vous. Et tout se fait avec l’aide d’ip en plus, que demande le peuple ?
Et si la conf réseau ça vous saoule, je trouverai à m’énerver sur d’autres choses (le larousse n’a qu’à bien se tenir).
Une quine en informatique, c’est un programme qui, quand il est exécuté, affiche un code source qui permet d’obtenir le même résultat. La plupart des quines affichent leur propre code. Évidement, ouvrir le fichier de code et l’afficher ne compte pas comme une quine valide…
C’est un exercice beaucoup plus difficile qui n’en à l’air, même si normalement tout langage turing complet en est capable.
Techniquement, la quine la plus courte en Python est un fichier vide, ce qui est une quine valide. Mais comme ce n’est pas très fun, voici un exemple court avec des vrais caractères ASCII dedans:
a='a=%s;print a%%`a`';print a%`a`
Notez l’emploie de variables qui ne servent à rien d’autre que d’optenir une forme de symétrie.
Une autre version plus longue :
b='\\';g='"';p='%';s="b='%s%s';g='%s';p='%s';s=%s%s%s;print s%s(b,b,g,p,g,s,g,p)";print s%(b,b,g,p,g,s,g,p)
Beaucoup de quines utilisent ce principe de créer une chaîne contenant une partie du programme et d’afficher et évaluer la chaîne en même temps. Parfois avec des boucles :
x = ['print "x =", x', 'for m in x: print m'] print "x =", x for m in x: print m
En Python, on peut évidement faire des variantes avec sys.write
, exec
, etc. Voici un article qui liste des snippets tordus et sympathiques pour y arriver.
Ça ne sert strictement à rien, mais c’est dimanche, personne ne va lire cet article de toute façon.