Régulièrement je passe un coup de dépoussiérage sur mes outils, et aujourd’hui c’est le tour du script de start up.
Pour ceux qui ne se souviennent pas, on peut utiliser la variable d’environnement PYTHONSTARTUP pour choisir un script de démarrage pour le shell.
Ca attend un chemin absolu vers un fichier Python, et donc sous Mac et Linux, on met dans son .bashrc
ou équivalent :
export PYTHONSTARTUP=/chemin/vers/son/script.py
Sous Windows, on ouvre une console et on fait :
SETX PYTHONSTARTUP c:\chemin\vers\son\script.py
Et dedans on peut mettre tout le code Python qu’on veut, ça sera lancé automatiquement quand on démarre le shell, mais PAS quand on lance un script Python.
Le script est exécuté dans l’espace de nom du shell, donc tous les imports du script sont mis à la disposition du shell. Du coup, pour moi il contient :
# -*- coding: utf-8 -*- # faut que ça marche pareil en P2 et P3 from __future__ import unicode_literals, print_function, absolute_import # Les imports des modules de la libs standars que j'utilise le plus # car à force çe me gave de les réimporter moi-même à chaque session import sys import os import re import json import csv import random import hashlib import tempfile import random import shelve import atexit import subprocess from glob import glob from uuid import uuid4 from pprint import pprint # on shadow le open() builtin histoire d'avoir toujours le # paramètre encoding from codecs import open from itertools import * from collections import * from datetime import datetime, timedelta # imports d'outils tierces parties que j'utilise souvent mais qui pourraient ne # pas être installés try: import arrow except ImportError: pass try: import requests except ImportError: pass try: from path import path except ImportError: pass try: from minibelt import * except ImportError: pass # activation d'autocompletion si ce n'est pas déjà le cas, notamment sous # des vieux shell Python ordinnaire try: import rlcompleter import readline readline.parse_and_bind("tab: complete") except ImportError: pass # si on est dans un virtual env env = os.environ.get('VIRTUAL_ENV') if env: # afficher le nom de l'env dans le prompt (marche pas dans ipython qui # a sa propre config pour ça) env_name = os.path.basename(env) sys.ps1 = '(%s) %s ' % (env_name, getattr(sys, 'ps1', '>>>')) # affichage une fois des modules installés avec pip pour qu'on sache # ce qu'on a a dispo dans cet env print("\nVirtualenv '{}' contains:\n".format(env_name)) cmd = subprocess.check_output([env + "/bin/pip", "freeze"], stderr=subprocess.STDOUT) try: cmd = cmd.decode('utf8') except: pass cmd = cmd.strip().split("\n") p = re.compile(r'(^.*\:\s)|((#|@).*$)|(==.*$)') print("'" + "', '".join(sorted(set(os.path.basename(p.sub('', f)) for f in cmd))) + "'\n") # alias pour printer rapidement p = print pp = pprint # avoir toujours un dossier temporaire près à l'usage TEMP_DIR = os.path.join(tempfile.gettempdir(), 'pythontemp') try: os.makedirs(TEMP_DIR) TEMP_DIR = path(TEMP_DIR) # si possible un objet path except Exception as e: pass # avoir un dico persistant pour garder des objets entre deux sessions. Pratique quand # on a un gros array numpy qu'on n'a pas envie de se faire chier à se recréer class Store(object): def __init__(self, filename): object.__setattr__(self, 'DICT', shelve.DbfilenameShelf(filename)) # cleaning the dict on the way out atexit.register(self._clean) def __getattribute__(self, name): if name not in ("DICT", '_clean'): try: return self.DICT[name] except: return None return object.__getattribute__(self, name) def __setattr__(self, name, value): if name in ("DICT", '_clean'): raise ValueError("'%s' is a reserved name for this store" % name) self.DICT[name] = value def _clean(self): self.DICT.sync() self.DICT.close() # Ainsi on peut faire store.foo = 'bar' et récupérer store.foo à la session # suivante. Moi je store tout dans un truc temporaire mais si vous voulez # garder la persistance entre deux reboots, il suffit de choisir un autre # dossier. python_version = "py%s" % sys.version_info.major try: store = Store(os.path.join(TEMP_DIR, 'store.%s.db') % python_version) except: print('\n/!\ Un session utilisant le store existe déjà. On ne peut pas partager un store.') |
Il est un peu relou puisqu’il faut qu’il marche pour P2 et P3…
Je me demande si je devrais pas faire un repo pour ce genre de truc.
Quelle sensation incroyable de découvrir une fonctionnalité comme ça, je suis joie et félicité !
Par contre je viens de tester et j’ai l’impression que tu as oublié un “import shelve” vu que j’ai une exception à ce propos au chargement du script…
En effet :) Trop de copier/coller.
Merci pr le topo, j’en ai pris quelques graines :)
Pour ceux que ça interesse, je pense qu’Autoenv fait partie des customizations a apporter a son shell.
https://github.com/kennethreitz/autoenv.git
MERCI !
Je retiens la classe Store.
Réciproquement, qu’est ce que vous conseillez pour une fonction restart qui réinitialise toutes les variables.
J’ai un truc moche:
def restart():
variables = [var for var in globals() if var[0] != "_" and var!='restart']
for var in variables:
del globals()[var]
Ca dépend de ce que tu veux faire, mais dans ton cas un c’est plus rapide (- de touches) de faire CTRL + D puis enter puis flèche du haut et enter pour relancer l’interpréteur que de taper restart() puisque les deux effacent absolument tout y compris les imports.
@francoisb
Vas poster ta question sur http://indexerror.net , ça évitera quelle se perde dans les méandres du blog et ça servira à quelqu’un d’autre un jour ;)
Pas besoin d’un repo : un gist c’est très bien !
https://gist.github.com/
avec python 3.4 ca hurle sur atexit not define que j’ai regle par un import plus haut
Anéfé
Rien à dire, génial ! Merci.