Python - Importing a global/site-packages module rather than the file of the same name in the local directory
I'm using python and virtualenv/pip. I have a module installed via pip called test_utils
(it's django-test-utils). Inside one of my django apps, I want to import that module. However I also have another file test_utils.py
in the same directory. If I go import test_utils
, then it will import this local file.
Is it possible to make python use a non-local / non-r开发者_运维百科elative / global import? I suppose I can just rename my test_utils.py
, but I'm curious.
You can switch the search order by changing sys.path:
del sys.path[0]
sys.path.append('')
This puts the current directory after the system search path, so local files won't shadow standard modules.
My problem was even more elaborate:
importing a global/site-packages
module from a file with the same name
Working on aero the pm recycler I wanted access to the pip api, in particular pip.commands.search.SearchCommand
from my adapter class Pip in source file pip.py.
In this case trying to modify sys.path
is useless, I even went as far as wiping sys.path
completely and adding the folder .../site-packages/pip...egg/
as the only item in sys.path
and no luck.
I would still get:
print pip.__package__
# 'aero.adapters'
I found two options that did eventually work for me, they should work equally well for you:
using __builtin__.__import__()
the built-in function
global_pip = __import__('pip.commands.search', {}, {}, ['SearchCommand'], -1)
SearchCommand = global_pip.SearchCommand
Reading the documentation though, suggests using the following method instead.
using importlib.import_module()
the __import__
conv wrapper.
The documentation explains that import_module()
is a minor subset of functionality from Python 3.1 to help ease transitioning from 2.7 to 3.1
from importlib import import_module
SearchCommand = import_module('pip.commands.search').SearchCommand
Both options get the job done while import_module()
definitely feels more Pythonic if you ask me, would you agree?
nJoy!
I was able to force python to import the global one with
from __future__ import absolute_import
at the beginning of the file (this is the default in python 3.0)
You could reset your sys.path
:
import sys
first = sys.path[0]
sys.path = sys.path[1:]
import test_utils
sys.path = first + sys.path
The first entry of sys.path
is "always" (as in "per default": See python docs) the current directory, so if you remove it you will do a global import.
Since my test_utils
was in a django project, I was able to go from ..test_utils import ...
to import the global one.
Though, in first place, I would always consider keeping the name of local file not matching with any global module name, an easy workaround, without modifying 'sys.path' can be to include global module in some other file and then import this global module from that file.
Remember, this file must be in some other folder then in the folder where file with name matching with global module is.
For example. ./project/root/workarounds/global_imports.py
import test_utils as tutil
and then in ./project/root/mycode/test_utils.py
from project.root.workarounds.global_imports import tutil
# tutil is global test_utils
# you can also do
from project.root.workarounds.global_imports import test_utils
精彩评论