Python how to alias module name (rename with preserving backward compatibility)

会有一股神秘感。 提交于 2019-12-06 02:23:57

问题


I have a python package named foo, which i use in imports:

import foo.conf
from foo.core import Something

Now i need to rename the foo module into something else, let's say bar, so i want to do:

import bar.conf
from bar.core import Something

but i want to maintain backward compatibility with existing code, so the old (foo.) imports should work as well and do the same as the bar. imports.

How can this be accomplished in python 2.7?


回答1:


This forces you to keep a foo directory, but I think it the best way to get this to work.

Directory setup:

bar
├── __init__.py
└── baz.py
foo
└── __init__.py

foo_bar.py

bar/__init__.py is empty.
bar/baz.py: worked = True

foo/__init__.py:

import sys

# make sure bar is in sys.modules
import bar
# link this module to bar
sys.modules[__name__] = sys.modules['bar']

# Or simply
sys.modules[__name__] = __import__('bar')

foo_bar.py:

import foo.baz

assert(hasattr(foo, 'baz') and hasattr(foo.baz, 'worked'))
assert(foo.baz.worked)

import bar
assert(foo is bar)



回答2:


Do you mean something like this?

import foo as bar

you can use shortcuts for module imports like:

from numpy import array as arr

in: arr([1,2,3])
out: array([1, 2, 3])

and you can also use more than one alias at a time

from numpy import array as foo
in: foo([1,2,3])
out: array([1, 2, 3])

if your foo is a class you can do:

bar=foo()

and call a subfunction of it by:

bar.conf()

Does this help you?




回答3:


This answer work with submodules:

import sys
import os
from importlib.abc import MetaPathFinder, Loader
import importlib
from MainModule.SubModule import *

class MyLoader(Loader):
    def module_repr(self, module):
        return repr(module)

    def load_module(self, fullname):
        old_name = fullname
        names = fullname.split(".")
        names[1] = "SubModule"
        fullname = ".".join(names)
        module = importlib.import_module(fullname)
        sys.modules[old_name] = module
        return module


class MyImport(MetaPathFinder):
    def find_module(self, fullname, path=None):
        names = fullname.split(".")
        if len(names) >= 2 and names[0] == "Module" and names[1] == "LegacySubModule":
            return MyLoader()


sys.meta_path.append(MyImport())


来源:https://stackoverflow.com/questions/24322927/python-how-to-alias-module-name-rename-with-preserving-backward-compatibility

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