Sam & Max » path 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 Path.py plus en détail 8 http://sametmax.com/path-py-plus-en-detail/ http://sametmax.com/path-py-plus-en-detail/#comments Tue, 08 Jan 2013 12:53:56 +0000 http://sametmax.com/?p=4036 La première fois que j’avais rencontré path.py, je l’avais trouvé “juste pratique”, et donc je n’avais pas passé plus de temps dessus. Un jour je me suis poussé à l’utiliser partout dans un projet type “labo” dans lequel je mettais plein de libs à l’épreuve du feu. Force est de constater que sur le long terme, cette bibliothèque fait gagner beaucoup à un projet pour un coût infime. Je l’inclus maintenant par défaut partout.

A quoi sert path.py ?

path.py est typiquement une lib qui ne sert à rien à première vue, car il n’y a rien qu’on puisse faire avec qu’on ne puisse déjà faire avec la lib standard de Python. C’est juste un wrapper autour de os, os.path et shutils. Un peu comme requests pour urllib en fait.

Elle permet juste de manipuler les fichiers, et chemin de fichiers. C’est tout.

Quel interêt alors ?

L’API est propre, cohérente, simple, intuitive. En un mot, c’est beau. On gagne du temps à l’usage, à la relecture et au debugging, car le code est devenu tout petit et tellement facile à comprendre. Mais le plus fort, c’est que le coût de transition est quasi nul: tout code utilisant path.py est par défault compatible avec le code précédent, sans changer une virgule.

Montre moi

<music>Lunatic Calm - Leave You Far Behind</music>

Installation (ceci dit ça tient dans un fichier…)

pip install path.py

On importe, et on créer un objet path à partir d’une chaîne de caractère représentant un chemin de fichier ou de dossier :

>>> from path import path
>>> tmp = path('/tmp/')

Manipuler un chemin de fichier n’a jamais été aussi facile

>>> new = tmp / 'new.txt' # "/" fait os.path.join()
>>> new
path('/tmp/new.txt')
>>> new.isfile()
False
>>> new.touch() # créer le fichier vide
>>> new.isfile()
True

Extraire des données également:

>>> new.ext
'.txt'
>>> new.name
path('new.txt')
>>> new.parent
path('/tmp')
>>> new.parent.parent
path('/')

C’est joli. On en mangerait. Notez que chaque méthode retourne un nouvel objet path() sur lequel on peut donc appliquer les mêmes méthodes.

En prime, un objet path() se comporte aussi comme une string:

>>> print new
/tmp/new.txt
>>> new.upper()
'/TMP/NEW.TXT'
>>> os.path.join(new.parent, 'new_new.txt')
path('/tmp/new_new.txt')

Du coup, aucun problème de migration de l’ancien code. Utiliser path.py n’a virtuellement que le coût de l’install et de l’import.

On a aussi accès à tout un tas de méthodes avancées:

>>> tmp.dirs() # listing du dossier courant
[path('/tmp/pulse-XnVNgklabjGI'), path('/tmp/ssh-vrCzN4692eCp'), path('/tmp/pulse-PKdhtXMmr18n'), path('/tmp/.truecrypt_aux_mnt1'), path('/tmp/.X11-unix'), path('/tmp/.ICE-unix'), path('/tmp/plugtmp'), path('/tmp/pulse-2L9K88eMlGn7'), path('/tmp/orbit-sam'), path('/tmp/.winbindd'), path('/tmp/tracker-sam')]
>>> tmp.files()
[path('/tmp/new.txt'), path('/tmp/backup_tem.zip'), path('/tmp/qtsingleapp-mediat-134e-3e8-lockfile'), path('/tmp/unity_support_test.0'), path('/tmp/apprentissage-130107043807-phpapp02.odp'), path('/tmp/nIzDHlLoho'), path('/tmp/.X0-lock'), path('/tmp/IDcRs0LUki')]
>>> tmp.files('*.txt') # filtres
[path('/tmp/new.txt')]
>>> tmp.walk() # walk, walkfiles et walkdirs == même chose, récursivement
<generator object walk at 0x2e17960>
>>> list(path('/etc/php5').walkfiles('*.ini'))
[path('/etc/php5/conf.d/10-pdo.ini'), path('/etc/php5/mods-available/pdo.ini'), path('/etc/php5/cli/php.ini'), path('/etc/php5/cli/conf.d/10-pdo.ini'), path('/etc/php5/apache2/php.ini'), path('/etc/php5/apache2/conf.d/10-pdo.ini')]
>>> (tmp / 'test/test/test').makedirs() # création récursive
>>> (tmp / 'test/test/test').isdir()
True
>>> (tmp / 'test/test/test').makedirs_p() # les "_p" ignorent certaines erreurs
>>> (tmp / 'test/test/test').removedirs()

Et quelques goodies:

>>> with path('./Work'):
    print path('.').realpath()
    print path('.').listdir()[0]
...     
/home/sam/Work
./A référencer
>>> path('~').expanduser()
path('/home/sam')
>>> path('/etc/fstab').open().readline()
'# /etc/fstab: static file system information.\n'
>>> new.write_text("BAM d'un coup")
>>> new.text()
"BAM d'un coup"

Très pratique dans un shell.

]]>
http://sametmax.com/path-py-plus-en-detail/feed/ 8
Variable d’environnement PATH et crontab 5 http://sametmax.com/variable-denvironnement-path-et-crontab/ http://sametmax.com/variable-denvironnement-path-et-crontab/#comments Fri, 26 Oct 2012 06:55:35 +0000 http://sametmax.com/?p=2741 Si vous utilisez crontab pour vos tâche, faites attention à un détail : le PATH.

il y a un fichier de conf que j’ai pas réussi à faire fonctionner dans /etc/crontab, si vous y arrivez tant mieux sinon éditez votre cron de la sorte:

1. Version avec PATH défini par tâche:

30 23 * * * PATH=$PATH:/usr/local/bin && export PATH && python /home/penetrator/script.py

2. Version avec variables définies en haut du fichier cron:

# Env
SHELL=/bin/bash
HOME=/home/prod
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
 
# Cmd cron
30 23 * * * python /home/penetrator/script.py

$PATH=PATH:/usr/local/bin && export PATH va rajouter /usr/local/bin dans le PATH.
Ayant installé et compilé un programme dans /usr/local/bin et l’utilisant dans script.py, il faut que son chemin soit dans le PATH.

Pour avoir des infos sur l’env de votre cron:

* * * * * PATH=$PATH:/usr/local/bin && export PATH && env > /tmp/cronenv

faites un tail -f /tmp/cronenv pour voir si votre PATH est bien déclaré.

ça peut éviter quelques heures à s’arracher les cheveux pour le debug d’un script…

]]>
http://sametmax.com/variable-denvironnement-path-et-crontab/feed/ 5
Ajouter un chemin à la variable d’environnement PATH sous Windows 11 http://sametmax.com/ajouter-un-chemin-a-la-variable-denvironnement-path-sous-windows/ http://sametmax.com/ajouter-un-chemin-a-la-variable-denvironnement-path-sous-windows/#comments Thu, 18 Oct 2012 20:19:16 +0000 http://sametmax.com/?p=2642 Il y a beaucoup de tutos qui demandent de simplement “ajouter le résultat au PATH”, mais assez peu expliquent pourquoi et comment le faire.

Comme on aime bien faire les choses à l’envers chez Sam et Max, on va d’abord expliquer comment, et ensuite pourquoi.

Modifier le PATH sous Windows 7 et XP

Il faut d’abord ouvrir l’outil d’édition des variables d’environnement.

Sous Windows XP, c’est:

  • Clic droit sur l’icône “Ordinateur” de votre Bureau (ou dans le panel de gauche de l’explorateur de fichiers) et dans le menu-contextuel, allez sur “Propriétés”.
  • Dans la fenêtre “Propriétés système” qui vient de s’ouvrir, allez dans l’onglet “Avancé”
  • Enfin, cliquez sur le bouton “Variables d’environnement…”

Sous Windows 7, c’est presque pareil:

  • Clic droit sur l’icône “Ordinateur” de votre Bureau (ou dans le panel de gauche de l’explorateur de fichiers) et dans le menu-contextuel, allez sur “Propriétés”.
  • Dans la grande fenêtre qui s’ouvre, cliquez sur le lien “Paramètres système avancés” dans la liste de gauche.
  • Dans la nouvelle fenêtre ainsi ouverte, cliquez sur le bouton “Variables d’environnement…”

Dans les deux cas, vous allez vous retrouver avec la fenêtre le plus détestée du monde de Windows, la fameuse fenêtre “Variables d’envionnement”. Toute petite, illisible, est pas redimensionable. Vous ne l’oublierez plus jamais:

Capture d'écran de la fenêtre des variables d'environnement de Windows

Oh mon dieu, il nous fonce dessus !

Dans cette fenêtre, dans la partie “Variables systèmes” (la liste du bas), il faut cliquer sur la ligne qui contient ‘Path’, de telle sorte qu’elle soit sélectionnée (en couleur alors que les autres items de la listes ne le sont pas). Il vous faudra sûrement scroller un peu pour la trouver.

Ensuite il faut cliquer sur le bouton “Modifier…”.

Là s’ouvre une fenêtre avec deux champs, le deuxième, “Valeur de la variable”, est celui qui nous intéresse. Il est absolument chiant à modifier, alors faites plutôt un copier/coller dans un éditeur de texte à part: Ctrl + A pour tout selectioner, Ctrl + C pour tout copier, puis Ctrl + V pour tout coller ailleurs, car je ne suis pas sûr que le clic droit fonctionne dans cette grosse bouse.

Vous devriez avoir un texte qui ressemble à ceci (pas exactement le même, mais proche):

%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\;

Ne retirez rien de cette valeur si vous ne savez pas ce que vous faites.

Pour ajouter quelque chose au PATH de Windows, il suffit de le mettre tout collé à la fin, suivit d’un ‘;’

Par exemple, pour rajouter le chemin vers l’installation de Python dans le PATH de Windows:

%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\;C:\Python27;

Attention, si vous avez copié/collé le contenu ailleurs, supprimez bien l’ancien contenu en le remplaçant complètement par le nouveau (Ctrl + A, Ctrl + V) sinon vous allez tout péter.

A quoi servent les variables d’environnement et le PATH ?

Sous tous les OS, il y a des variables qui déterminent le fonctionnement de celui-ci (ou plutôt du shell, mais ce n’est pas important). Elles permettent à l’utilisateur, en changeant la variable, de choisir certains comportement primitifs du système.

Par exemple, quand vous tapez une commande dans un terminal, le système va utiliser la variable d’environnement PATH. Il va prendre chaque dossier listé dans PATH, et regarder si il trouve la commande dedans. Si il trouve cette commande, il la lance, et arrête la recherche. Si il ne trouve pas la commande, il va vous dire que la commande n’existe pas.

Ainsi, si vous avez installé Python mais que le shell Python ne se lance pas quand vous entrez la commande python dans un terminal, ajouter C:\Python27; au PATH peut résoudre le problème: Windows va maintenant chercher dans ce dossier également pour voir si la commande existe.

]]>
http://sametmax.com/ajouter-un-chemin-a-la-variable-denvironnement-path-sous-windows/feed/ 11
Se faciliter les imports avec les fichiers *.pth 1 http://sametmax.com/se-faciliter-les-imports-avec-les-fichiers-pth/ http://sametmax.com/se-faciliter-les-imports-avec-les-fichiers-pth/#comments Mon, 10 Sep 2012 16:49:24 +0000 http://sametmax.com/?p=2082 *.pth. Néanmoins cette extension est souvent mal comprise, et voici un comment en profiter au maximum.]]> Dans un article, nous parlions des extensions alternatives en Python, et notamment de l’usage des fichiers *.pth. Néanmoins cette extension est souvent mal comprise, et voici un comment en profiter au maximum.

En Python, on a souvent des problèmes d’import: la lib est dans un dossier au dessous, ou à côté, ou à l’autre bout du disque dur, et ça plantouille parceque Python ne trouve pas le module.

Il existe plein de moyens de jouer avec le fameux PYTHON_PATH qui contient la liste des dossiers dans lesquelles chercher les libs, et la plupart sont fort verbeuses et répétitives, du genre:

import os
import sys
 
CUR_DIR = os.path.dirname(os.path.realpath(__file__))
sys.path.extend([
    os.path.join(CUR_DIR, 'apps'),
    os.path.join(os.path.dirname(CUR_DIR), 'libs'),
    os.path.join(os.path.realpath('~'), '.local_libs')
]]}

Une manière simple est d’utiliser un fichier *.pth: on créé un fichier texte, on le nomme comme-on-veut.pth (moi je me fais pas chier, je le nomme .pth comme ça c’est court et c’est caché sous nunux), et on liste tous les dossiers qu’on veut ajouter au PYTHON_PATH, y compris avec des chemins relatifs.

Oui mais, argh parmi les argh, la première fois qu’on le fait, ça ne marche pas. Alors on cherche dans la doc, et là, fustration, on apprend que les fichiers *.pth ne sont parsés que dans les sites directories, c’est à dire les dossiers officiels du système dans lesquels sont censés être les libs de la bibliothèque standard. Donc pas le dossier courant.

Eh oui, ces fichiers ont été conçus pour faciliter les déploiements, du genre quand on fait un setup.py pour son app, pas pour nous, pauvres mortels.

Heureusement il y a une solution Sam et Max à tout, et ici elle consiste à faire:

import os
import site
 
CUR_DIR = os.path.dirname(os.path.realpath(__file__))
site.addsitedir(CUR_DIR)

Quelque part dans son code n’importe où qui est sûr d’être éxécuté tôt, par exemple dans Django, dans le settings.py. Ca ajoute le dossier du projet en tant que site directory, et donc le fichier .pth est parsé. On peut alors dumper son listing dedans sans avoir à le répéter dans tous les scripts et fichiers qui doivent l’utiliser (et ainsi modifier cette liste facilement).

Attention cependant, celà rajoute votre dossier de projet dans le PYTHON_PATH, rendant tout ce qu’il contient importable. Normalement, c’est ce que vous voulez, mais si ce n’est pas le cas, vous pouvez avoir une gestion plus fine en ajoutant juste le fichier .pth avec site.addpackage(CUR_DIR, 'fichier.pth', set())

La feature de magie noire

Dans les fichiers *.pth, il y a un support limité de la syntaxe Python: on peut commenter des lignes avec # et faire des import truc.

Sauf que si vous êtes curieux, vous verrez le détail qui tue dans l’implémentation:

if line.startswith(("import ", "import\t")):
    exec line

On peut donc virtuellement mettre n’importe quel code Python dans les fichiers *.pth. Par exemple:

../foo
import sys; print "Foo a été ajouté au PYTHON PATH"

Va afficher “Foo a été ajouté au PYTHON PATH” au démarrage du programme. Amusant. Et tellement de potentiels pour faire des trucs tordus !

]]>
http://sametmax.com/se-faciliter-les-imports-avec-les-fichiers-pth/feed/ 1