PROJET AUTOBLOG


Sam & Max: Python, Django, Git et du cul

Site original : Sam & Max: Python, Django, Git et du cul

⇐ retour index

Mise à jour

Mise à jour de la base de données, veuillez patienter...

Fichiers temporaires avec tempfile en Python

dimanche 14 juillet 2013 à 03:21

Il est de ces petits modules qui sont tout simples et bien pratiques. Et la lib standard de Python en regorge. Aujourd’hui (cette nuit, ce matin, choisissez votre référentiel, pour moi c’est le petit dej), on va voir le module tempfile.

Il permet de manipuler des fichiers et dossiers – qui après tout sont des fichiers – temporaires, c’est à dire jetable, en quelque sorte.

Donc :

>>> import tempfile

Dossier temporaire

La fonction la plus simple permet d’obtenir le dossier de l’OS dans lequel on met généralement les fichiers temporaires, comme par exemple C:\TEMP, C:\TMP, /tmp, /var/tmp, ou /usr/tmp selon la machine, l’OS, les variables d’environnement. Sur ma machine :

>>> tempfile.gettempdir()
'/tmp'

Si vous avez juste besoin d’un dossier temporaire dans lequel travailler :

>>> tempfile.mkdtemp()
'/tmp/tmps01VJw'

Il va être créé et sera accessible en lecture et écriture pour l’utilisateur qui l’a créé (permissions 700 sous Linux par exemple). Le chemin est retourné sous forme de string, à charge de votre programme de le supprimer, ou laisser l’OS s’en charger naturellement au prochain reboot.

Fichier temporaire

Il existe plusieurs manière de créer un fichier temporaire avec ce module, mais je vous invite à utiliser principalement :

>>> f = tempfile.NamedTemporaryFile()
>>> f
<open file '<fdopen>', mode 'w+b' at 0x1b7fc00>
>>> f.name
'/tmp/tmp0FxO_c'

C’est la méthode la plus simple et la plus passe-partout. Vous pouvez oublier mktemp(), mkstemp(), TemporaryFile(), etc. Le fichier est automatiquement supprimé quand vous appelez close() dessus, à moins de passer False via le paramètre delete.

Au passage vous pouvez influencer le nom du fichier résultant en passant prefix, suffix, et dir en arguments.

>>> tempfile.NamedTemporaryFile(prefix='~').name
u'/tmp/~XAoApc'
>>> tempfile.NamedTemporaryFile(suffix="tmp").name
u'/tmp/tmpbirE0Jtmp'
>>> tempfile.NamedTemporaryFile(suffix=".tmp").name
u'/tmp/tmpm4iHXE.tmp'
>>> tempfile.NamedTemporaryFile(dir="/home/sam/.tmp").name
u'/home/sam/.tmp/tmpHfwhQI'
>>> tempfile.NamedTemporaryFile(dir="/home/sam/.tmp").name

mode et bufsize sont aussi disponibles, et seront relayés à file() sous le capot.

>>> tempfile.
tempfile.NamedTemporaryFile    tempfile.TMP_MAX               tempfile.gettempdir            tempfile.mkdtemp               tempfile.mktemp                tempfile.template
tempfile.SpooledTemporaryFile  tempfile.TemporaryFile         tempfile.gettempprefix         tempfile.mkstemp               tempfile.tempdir
>>> tempfile.get
tempfile.gettempdir     tempfile.gettempprefix
>>> tempfile.gettempdir()
'/tmp'

Une dernière astuce qui ne m’a jamais servi : tempfile.SpooledTemporaryFile(max_size=X). Similaire à NamedTemporaryFile, mais le fichier est uniquement en mémoire, et sera transformé en un fichier sur le disque si sa taille dépasse X octets. StringIO est utilisé pour la partie en RAM.

Le fait de demander son file descriptor (l’entier qui représente le fichier pour le programme) le fait aussi passer en mode “sur le disque” :

>>> a = tempfile.SpooledTemporaryFile(max_size=10000)
>>> a.name
Traceback (most recent call last):
  File "<ipython-input-43-c0a6f6c60584>", line 1, in <module>
    a.name
  File "/usr/lib/python2.7/tempfile.py", line 569, in name
    return self._file.name
AttributeError: 'cStringIO.StringO' object has no attribute 'name'
 
>>> a.fileno()
9
>>> a.name
'<fdopen>'

flattr this!

Créer un décorateur à la volée

vendredi 12 juillet 2013 à 07:39

Sur les décorateurs, normalement, vous avez tout ce qu’il faut pour être au point.

Néanmoins en informatique la moitié de la connaissance, c’est l’usage, pas la fonctionnalité. Car il y beaucoup d’usages auxquels on ne pense pas.

Particulièrement, je vous avais déjà expliqué que les fonctions étaient des objets comme les autres en Python, et qu’on pouvait donc les créer à la volée, les retourner, les passer en paramètre, et même leur coller des attributs.

Or les décorateurs ne sont jamais que des fonctions.

Maintenant, souvenez vous, le décorateurs property permet de faire ceci :

class Mamouth(object):
 
    _valeur = "3 calots"
 
    @property
    def valeur(self):
        return self._valeur.upper()
 
    @valeur.setter
    def valeur(self, valeur):
        self._valeur = valeur.strip()
 
>>> bille = Mamouth()
>>> bille.valeur
u'3 CALOTS'
>>> bille.valeur = "une pépite           "
>>> bille.valeur
>>> print(bille.valeur)
UNE PÉPITE

La syntaxe qui doit attirer votre attention est @valeur.setter. En effet, d’où vient ce décorateur ?

On comprend mieux ce qui s’est passé avec ce test :

>>> Mamouth.valeur.setter
<built-in method setter of property object at 0x1a1baf8>

setter est tout simplement un attribut de la méthode valeur. Par ailleurs, c’est une fonction et un décorateur.

Pourquoi faire cela ? Et bien tout simplement parce que cela permet d’attacher une fonction qui ne sert que dans un cas (ici ça ne sert qu’à créer le setter de la propriété valeur) à son contexte.

Bien entendu vous pouvez faire ça vous même, il suffit de le vouloir très fort et de croire en le pouvoir de l’amour.

Par exemple, imaginez un décorateur qui permet d’attacher un comportement de sérialisation à une fonction. On ne veut pas modifier la fonction, mais on veut qu’elle puisse automatiquement, pour quelques caractères de plus, pouvoir aussi retourner du JSON ou du pickle.

import json
import pickle
 
def serializable(func):
 
    # Contrairement à la plupart des décorateurs, on ne va pas retourner
    # un wrapper, mais bien la fonction originale. Simplement on lui aura ajouté
    # des attributs
 
    func.as_json = lambda *a, **k: json.dumps(func(*a, **k))
    func.as_pickle = lambda *a, **k: pickle.dumps(func(*a, **k))
 
    return func

Et ça s’utilise ainsi :

import locale
 
from calendar import TimeEncoding, day_name, day_abbr
 
# obtenir les noms de jours localisés est complètement rocambolesque en python
def get_day_name(day_number, locale, short=False):
    """
        Retourne le nom d'un jour dans la locale sélectionnée.
 
        Exemple :
 
        >>> get_day_name(0,  ('fr_FR', 'UTF-8'))
        'lundi'
    """
    with TimeEncoding(locale) as encoding:
        s = day_abbr[day_number] if short else day_name[day_number]
        return s.decode(encoding) if encoding is not None else s
 
@serializable
def get_days_names(locale=locale.getdefaultlocale(), short=False):
    """
        Un dictionnaire contenant un mapping entre les numéros des jours
        de semaine et leurs noms selon la locale donnée.
    """
 
    return {i: get_day_name(i, locale) for i in xrange(7)}

En usage ordinaire, la fonction retourne bien ce qui est prévu :

>>> get_days_names()
{0: 'lundi', 1: 'mardi', 2: 'mercredi', 3: 'jeudi', 4: 'vendredi', 5: 'samedi', 6: 'dimanche'}
>>> get_days_names(locale=('en_US', 'UTF-8'))
{0: 'Monday', 1: 'Tuesday', 2: 'Wednesday', 3: 'Thursday', 4: 'Friday', 5: 'Saturday', 6: 'Sunday'}

Mais on peut choisir le format à la sortie :

>>> get_days_names.as_json()
'{"0": "lundi", "1": "mardi", "2": "mercredi", "3": "jeudi", "4": "vendredi", "5": "samedi", "6": "dimanche"}'
>>> get_days_names.as_pickle(locale=('en_US', 'UTF-8'))
"(dp0\nI0\nS'Monday'\np1\nsI1\nS'Tuesday'\np2\nsI2\nS'Wednesday'\np3\nsI3\nS'Thursday'\np4\nsI4\nS'Friday'\np5\nsI5\nS'Saturday'\np6\nsI6\nS'Sunday'\np7\ns."

Ici, on a attacher une fonction à une autre fonction, en mettant la deuxième dans un attribut de la première.

Comme les décorateurs sont des fonctions, rien ne vous empêche de faire pareil avec un décorateur, et c’est de cette manière que @property attache un décorateur setter à chaque méthode.



Télécharger le code des articles

flattr this!

Ceci n’est pas un benchmark…

jeudi 11 juillet 2013 à 08:08

… mais quand même. Il va falloir sérieusement étudier le passage de nos sites à pypy.

$ pypy --version
Python 2.7.2 (1.8+dfsg-2, Feb 19 2012, 19:18:08)
[PyPy 1.8.0 with GCC 4.6.2]
 
$ date; pypy -c "for x in xrange(1000000000): pass"; date
mardi 9 juillet 2013, 12:30:58 (UTC+0200)
mardi 9 juillet 2013, 12:31:09 (UTC+0200)
 
$ python --version
Python 2.7.3
 
$ date; python -c "for x in xrange(1000000000): pass"; date
mardi 9 juillet 2013, 12:31:16 (UTC+0200)
mardi 9 juillet 2013, 12:32:49 (UTC+0200)

flattr this!

La Joconde n’est autre qu’un Ladyboy

mercredi 10 juillet 2013 à 07:42

Ces derniers jours, marqueurs véritables d’une productivité fulgurante de ma part m’ont ammené à me perdre sur Youtube.

En me baladant de documentaires en documentaires, sur la reproduction asexuée des anémones de mer à la dance tribale des papous d’océanie entre autre.
Je suis tombé sur un reportage qui présente Leonardounet non pas comme le super peintre que l’on connait mais sous une autre facette (en fait plusieurs mais celle-là est chouette).

Une théorie nous apprend que la Joconde serait Salai, le petit garçon amant de notre cher Leonard.

En fait si vous ne voulez pas vous taper le doc en entier je vous fais illico presto la synthèse:

Leonard De Vinci serait donc un pédophile d’1m95 qui a peint à 2 reprises son gentil petit garçon de joie dont une sous les traits de la Joconde, organisait des sodomies festives avec ses potes et collectionnait les mecs.

Des millions de personnes l’admirent, le vénèrent de part le monde, ses reliques se vendent des millions et on me dit que je suis dégueulasse quand je met le doigt dans mon nez.

C’était la minute inutile de Max. Bonne journée.

PS: On comprend mieux comment lui est venue l’idée d’inventer le sous-marin

flattr this!

Première requête de take down pour 0bin

mardi 9 juillet 2013 à 08:21

Vous vous souvenez, 0bin, ce pastebin chiffré côté client écrit en Python ? Le but était de protéger, non pas l’utilisateur, mais l’hébergeur, d’une attaque en justice. La théorie est qu’il ne peut en effet être tenu de modérer ce qu’il ne peut consulter.

Et bien on vient de recevoir notre première demande légale de retrait de liens.

Petit retour sur les faits, pistes de réflexion et appel à commentaires.

Le take down

La demande ne nous est pas parvenue directement, ni même par notre hébergeur, mais via notre fournisseur de nom de domaine, en l’occurrence pour 0bin.net, l’américain namecheap.

Techniquement, nous ne sommes pas aux USA, et nos serveurs ne le sont pas non plus. Pour Max, “c’est idiot de se prendre un procès pour un site qui rapporte pas”. Moi je dirais plutôt que le risque, c’est de perdre le nom de domaine qui est quand même super cool, mais ma première réaction a plutôt été “nannnnnnn, faut pas censurer”. Au final, on quand même retiré les pastes, puisqu’ils contenaient des liens de téléchargement de contenus protégés par le droit d’auteur.

Voici les demandes que nous avons reçu :

2.) Identify the copyrighted work claimed to have been infringed
You link to this copyrighted material (music albums):

DANNY PRESZ – Inicio – (2013)
ORQUESTA BRONKO & SHAKAITO – 30 Aniversario-Homenaje – (2013)
CHARLIE CRUZ – Huellas – (2013)
MONGORAMA – Baila Que Baila – (2013)
CONJUNTO SABROSURA – Moña Pa’ Mi Bongó – (2013)
V. A. – Sergio George’s Salsa Giants – (2013)
Victor Manuelle – Me Llamaré Tuyo – (2013)

3.) Provide us the exact location of the infringing file with the exact link
On your servers here (re-directing to 180upload.com):

http://0bin.net/paste/7eefb6647bb1e606ef95eaa219e4f2de8ef98d5a#GipoKK++q7p3t+56MQPQa7Tm50Vq3BTATm0a9CsiBE0=

http://0bin.net/paste/d3d3db7281b32d1d9ba4be1f0166c0e6681b7904#yuYfcO5g83WDQ7xgF8l39AhHJH4N+XfzMv6Th1IoiVo=

http://0bin.net/paste/4185de7d1d5acc69f149472edb6395603786e622#s22bq9IkdWlm7vajb4+ryNvQLAe79tYZqrICzaexw1E=

http://0bin.net/paste/df3bf3537bec0d54c1fc2d469307d91674172072#uTszh1/Om8baR/hsvWpLyMm50vgwRoRRsMkMbgVouTo=

http://0bin.net/paste/1cbb4a2796db7015412353e9cc6818cd16673338#spj9KqFNfCeMR/VNN5IVof4Sax9njevkcIBuesNWTmE=

http://0bin.net/paste/f67fd84d81bdfeb5da8a529a1064d143c8831fe6#uadJcY9uIaGbJ7oXUZ8kcXXpiktHjwkhE9XUH3TC+9U=

http://0bin.net/paste/a1043ecdf4fe1d1a4d55aedc5d9409f1767223ef#QaT1pCopGaxs9ZC07N+0cmVg6aRoiL9uY3GOPvuUx7w=

4.) Provide us the web address under which the link has been published
The links are shared here in public:

http://bypachayo.blogspot.de/

J’ai groupé les mails en un seul, mais il y en a eu 3. Notez qu’ils avaient accès aux liens avec la clé de chiffrement, puisqu’ils étaient posté publiquement sur un blog. De plus, l’identification a probablement été manuelle étant donné la nature de 0bin.

L’état de 0bin

0bin n’est pas un outil de lutte contre la censure ou de contournement légal. Il n’est pas armé pour le cas où la demande de take down arrive avec le lien complet, clé incluse, car il a été exposé ainsi sur le Net.

Il ne permet pas non plus de prévenir l’utilisateur du retrait de ses liens : tout le monde va tomber sur une 404 jusqu’à ce que l’auteur soit averti, et il ne comprendra pas ce qui s’est passé.

Ici, on a eu la chance d’avoir un seul blog, donc je suis allé poster un commentaire dessus pour lui expliquer la situation. Mon espagnol est un peu rouillé d’ailleurs.

On voit aussi que 0bin, et Internet en général, est mal compris : le mec utilisait l’outil pour poster un lien par paste, qu’il linkait ensuite sur son site. Qu’espérait-il ? Camoufler quelque chose ? A-t-il compris comment marchait le service ? A quoi il était destiné ?

La seule bonne nouvelle dans tout ça, c’est qu’on a rajouté un script qui supprime permet de supprimer un paste en Python.

Et après ?

Même si les liens étaient illégaux (d’ailleurs je n’ai aucune connaissance pour vérifier que l’injonction de retrait est elle, légale), cela fait toujours un peu chier de devoir retirer quelque chose. Cette fois, on n’a pas recopié l’information ailleurs, mais peut être qu’on aurait dû.

La vraie question c’est : est-ce qu’on veut ajouter des fonctionnalités de résistance contre la censure à 0bin ? Est-ce que ce but est vraiment complémentaire à l’objectif initial ? Est-ce que les utilisateurs en ont besoin ? Est-ce que ça ne va pas transformer le logiciel en un truc qui n’a rien à voir ?

Et si oui, que mettre en place ? De mon chapeau, j’ai déjà quelques idées :

Mais rien de tout ça ne règle le problème de notre cher fan de Danny Presz. D’ailleurs faut-il résoudre son problème ? Et si oui, est-ce le rôle de 0bin ?

J’ai horreur de terminer une article comme ça, ça fait vraiment pute à commentaires sur un blog cheap, mais qu’est-ce que vous en pensez ?

flattr this!

Error happened! 0 - count(): Argument #1 ($value) must be of type Countable|array, null given In: /var/www/ecirtam.net/autoblogs/autoblogs/autoblog.php:428 http://ecirtam.net/autoblogs/autoblogs/sametmaxcom_a844ada43a979e3b1395ab9acb6afafb84340999/?145 #0 /var/www/ecirtam.net/autoblogs/autoblogs/autoblog.php(999): VroumVroum_Blog->update() #1 /var/www/ecirtam.net/autoblogs/autoblogs/sametmaxcom_a844ada43a979e3b1395ab9acb6afafb84340999/index.php(1): require_once('...') #2 {main}