Python - Importing a global/site-packages module rather than the file of the same name in the local directory

拥有回忆 提交于 2019-12-24 09:39:08

问题


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.


回答1:


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.




回答2:


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!




回答3:


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)




回答4:


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.




回答5:


Since my test_utils was in a django project, I was able to go from ..test_utils import ... to import the global one.




回答6:


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


来源:https://stackoverflow.com/questions/5299199/python-importing-a-global-site-packages-module-rather-than-the-file-of-the-sam

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!