55 votes

À quoi sert __path__?

Je n'avais jamais remarqué l' __path__ attribut est défini sur certains de mes paquets avant aujourd'hui. Selon la documentation:

Paquets prennent en charge un plus spécial attribut, __path__. C'est initialisé à une liste contenant le nom du répertoire contenant les paquet __init__.py avant le code dans ce fichier est exécuté. Cette variable peut être modifiée; le faire affecte les futures recherches sur les modules et des sous-paquets contenus dans le package.

Bien que cette fonctionnalité n'est pas souvent de besoin, il peut être utilisé pour étendre la ensemble de modules trouvés dans le paquet.

Quelqu'un pourrait m'expliquer exactement ce que cela signifie et pourquoi je n'aurais jamais envie de l'utiliser?

35voto

Ian Bicking Points 4571

Il est généralement utilisé avec pkgutil de laisser un package d'être mis sur le disque. E. g., zope.interface et zope.le schéma sont séparés des distributions (zope est un "espace de noms de paquets"). Vous pourriez avoir zope.interface installée en /usr/lib/python2.6/site-packages/zope/interface/, tandis que vous êtes à l'aide de zope.schéma plus localement en /home/me/src/myproject/lib/python2.6/site-packages/zope/schema.

Si vous mettez de l' pkgutil.extend_path(__path__, __name__) en /usr/lib/python2.6/site-packages/zope/__init__.py alors zope.interface et zope.schéma sera importable car pkgutil aura du changement __path__ de ['/usr/lib/python2.6/site-packages/zope', '/home/me/src/myproject/lib/python2.6/site-packages/zope'].

pkg_resources.declare_namespace (une partie de Setuptools), c'est comme pkgutil.extend_path , mais est de plus en plus conscients de zips sur le chemin.

Modifier manuellement __path__ est rare et n'est probablement pas nécessaire, mais il est utile de regarder la variable lors du débogage des problèmes d'import de noms de paquets.

Vous pouvez également utiliser __path__ pour monkeypatching, par exemple, j'ai monkeypatched distutils à la fois par la création d'un fichier distutils/__init__.py c'est tôt, sys.path:

import os
stdlib_dir = os.path.dirname(os.__file__)
real_distutils_path = os.path.join(stdlib_dir, 'distutils')
__path__.append(real_distutils_path)
execfile(os.path.join(real_distutils_path, '__init__.py'))
# and then apply some monkeypatching here...

32voto

Syntactic Points 4068

Si vous modifiez __path__ , vous pouvez forcer l'interprète à rechercher dans un répertoire différent les modules appartenant à ce package.

Cela vous permettrait, par exemple, de charger différentes versions du même module en fonction des conditions d'exécution. Vous pouvez le faire si vous souhaitez utiliser différentes implémentations de la même fonctionnalité sur différentes plates-formes.

7voto

Matt Anderson Points 7461

En plus de sélectionner les différentes versions d'un module de base sur les conditions d'exécution comme Syntaxiques dit, cette fonctionnalité vous permettra de casser votre paquet en plusieurs morceaux / télécharge / installe tout en conservant l'apparence d'une logique unique paquet.

Considérons l'exemple suivant.

  • J'ai deux paquets, mypkg et _mypkg_foo.
  • _mypkg_foo contient le module optionnel d' mypkg, foo.py.
  • téléchargé et installé, mypkg ne contient pas d' foo.py.

mypkgs' __init__.py pouvez faire quelque chose comme ça:

try:
    import _mypkg_foo
    __path__.append(os.path.abspath(os.path.dirname(_mypkg_foo.__file__)))
    import mypkg.foo
except ImportError:
    pass

Si quelqu'un a installé le package _mypkg_foo, alors mypkg.foo est disponible pour eux. Si elles n'ont pas, il n'existe pas.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X