Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is __path__ useful for?

I had never noticed the __path__ attribute that gets defined on some of my packages before today. According to the documentation:

Packages support one more special attribute, __path__. This is initialized to be a list containing the name of the directory holding the package’s __init__.py before the code in that file is executed. This variable can be modified; doing so affects future searches for modules and subpackages contained in the package.

While this feature is not often needed, it can be used to extend the set of modules found in a package.

Could somebody explain to me what exactly this means and why I would ever want to use it?

like image 876
Jason Baker Avatar asked Apr 23 '10 14:04

Jason Baker


People also ask

What does __ file __ mean in Python?

__file__ is the pathname of the file from which the module was loaded, if it was loaded from a file. The __file__ attribute is not present for C modules that are statically linked into the interpreter; for extension modules loaded dynamically from a shared library, it is the pathname of the shared library file.

What is the use of __ init __ file?

The __init__.py file makes Python treat directories containing it as modules. Furthermore, this is the first file to be loaded in a module, so you can use it to execute code that you want to run each time a module is loaded, or specify the submodules to be exported.

What is Pkgutil in Python?

Source code: Lib/pkgutil.py. This module provides utilities for the import system, in particular package support.

How does Python find packages?

Python imports work by searching the directories listed in sys. path . So Python will find any packages that have been installed to those locations.


2 Answers

This is usually used with pkgutil to let a package be laid out across the disk. E.g., zope.interface and zope.schema are separate distributions (zope is a "namespace package"). You might have zope.interface installed in /usr/lib/python2.6/site-packages/zope/interface/, while you are using zope.schema more locally in /home/me/src/myproject/lib/python2.6/site-packages/zope/schema.

If you put pkgutil.extend_path(__path__, __name__) in /usr/lib/python2.6/site-packages/zope/__init__.py then both zope.interface and zope.schema will be importable because pkgutil will have change __path__ to ['/usr/lib/python2.6/site-packages/zope', '/home/me/src/myproject/lib/python2.6/site-packages/zope'].

pkg_resources.declare_namespace (part of Setuptools) is like pkgutil.extend_path but is more aware of zips on the path.

Manually changing __path__ is uncommon and probably not necessary, though it is useful to look at the variable when debugging import problems with namespace packages.

You can also use __path__ for monkeypatching, e.g., I have monkeypatched distutils at times by creating a file distutils/__init__.py that is early on 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... 
like image 177
Ian Bicking Avatar answered Sep 28 '22 02:09

Ian Bicking


If you change __path__, you can force the interpreter to look in a different directory for modules belonging to that package.

This would allow you to, e.g., load different versions of the same module based on runtime conditions. You might do this if you wanted to use different implementations of the same functionality on different platforms.

like image 22
Syntactic Avatar answered Sep 28 '22 01:09

Syntactic