简体   繁体   中英

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-relative / 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!

我能够通过文件开头的from __future__ import absolute_import强制python导入全局文件(这是python 3.0中的默认设置)

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

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.

由于我的test_utils在django项目中,因此我可以from ..test_utils import ...导入全局项目。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM