Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to import standard library module instead of local directory?

Tags:

python

I have a local directory named "calendar" with an "__init__.py" file.

I want "import calendar" to import the standard library module calendar, and not the module defined by my local directory.

I already tried "from __future__ import absolute_import" and changing PYTHONPATH.

There are Good Reasons I can't just rename the directory. Really.

like image 490
Jonathan Paulson Avatar asked Jan 02 '14 23:01

Jonathan Paulson


People also ask

How can I import modules if file is not in same directory?

We can use sys. path to add the path of the new different folder (the folder from where we want to import the modules) to the system path so that Python can also look for the module in that directory if it doesn't find the module in its current directory.

How do I import a module from the root directory?

In order to import a module, the directory having that module must be present on PYTHONPATH. It is an environment variable that contains the list of packages that will be loaded by Python. The list of packages presents in PYTHONPATH is also present in sys. path, so will add the parent directory path to the sys.

Can you manually import a module in Python?

append() Function. This is the easiest way to import a Python module by adding the module path to the path variable. The path variable contains the directories Python interpreter looks in for finding modules that were imported in the source files.


1 Answers

The problem is that the current working directory (as either '' or '.', depending on version/platform) is always at the top of sys.path when you start up Python.

Using absolute imports makes no difference—that just means to look in sys.path first, instead of looking for relative imports before falling back to sys.path.

The right solution is obviously to either (a) rename calendar, or (b) move it into subpackage of some other package instead of having it at the top level. Whatever your Good Reasons are, the Good Reasons for doing the right thing are likely even better.


But if you must get around this, there are a few things you can do. The simplest is to temporarily munge sys.path:

syspath = sys.path
sys.path = [path for path in sys.path if path.strip('.')]
import calendar
sys.path = syspath

However, no matter what you do, this is going to cause huge problems. When you later try to import your local package calendar—even if you're doing so from a completely different source file—nothing will happen, because there's already something named calendar in sys.modules, so that other source file will just get the stdlib calendar module instead of your package.

So you'll also need to rename one or the other on the fly and remove it from sys.modules. Maybe this:

syspath = sys.path
sys.path = [path for path in sys.path if path.strip('.')]
calmod = sys.modules.get('calendar')
del sys.modules['calendar']
calendar = __import__('calendar')
sys.modules['calendar'] = calmod
sys.path = syspath

And, depending on the order at which your modules get run (which may not be easily predictable, or even deterministic), there's a good chance you'll need similar hackery in the other location.

(What if you never actually need to import your local package calendar? Well, in that case you don't have this problem… but then I can't imagine what your Good Reasons could possibly be…)

like image 159
abarnert Avatar answered Oct 12 '22 22:10

abarnert