开发者

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜