导入与python 3中内置模块同名的模块

2sbarzqh  于 2022-11-26  发布在  Python
关注(0)|答案(3)|浏览(187)

我遇到了一个类似的问题,可以简化为:
例如,我有一个文件结构如下:

----folder
    ---- main.py
    ---- math.py

我在math.py中定义了一个函数,我想将这个math.py导入到main.py中。
math.py中的代码如下

# math.py
def f(x) :
    return x**3

如果我在main.py中写代码如下

# main.py
import math

def main() :
    print(math.f(3))

if __name__ == "__main__":
    main()

则返回AttributeError: module 'math' has no attribute 'f'
如果我在main.py中写代码如下

# main.py
from . import math

def main() :
    print(math.f(3))

if __name__ == "__main__":
    main()

然后返回ImportError: cannot import name 'math' from '__main__' (main.py)
我的问题:
1.如果我想导入路径folder中与内置模块同名的模块math.py,该怎么办?
1.如果在main.py中我想同时使用**math.f(x)中定义的 * math.py和内置的math.acos(x),我该怎么办?
附言:我也遇到过类似的问题,因为我有一个十年前别人写的很长的代码,那个时候没有这个名字的内置模块(其实不是math模块,我只是通过上面的问题把问题简化了),而且这个模块的功能已经被很多地方使用了,所以要修改模块几乎不可能。的名字,因为如果这样的话,我需要仔细改变所有的网站module.function()

vfh0ocws

vfh0ocws1#

用内置模块来命名模块是一个很糟糕的习惯,我建议你math.py用其他的名字来命名www.example.com。
也就是说,您可以使用带有imp的路径导入它:

import imp
math = imp.load_source('math', './math.py')
wgxvkvu9

wgxvkvu92#

潜入一个兔子洞,但在这里,我们去。作为免责声明,就像杰克说的命名模块后,内置是非常糟糕的做法,这可以更容易地完成使用imp,因为他建议。
你遇到问题的原因来自于一些事情的相互作用。

import math

你的python所做的就是查看sys.path。它将在sys.path中的所有位置检查一个名为math的模块,并导入它找到的第一个模块。在你的例子中,它首先找到你的本地math模块。导入完成后,它将它添加到sys.modules中,但我们将回到这个问题上。
既然你想同时使用这两种方法,首先你可以导入你的本地数学。我建议导入它作为一个不同的名称,以保持它的独立性。

from . import math as local_math

之后,我们需要修改系统路径以找到内置的数学函数。

sys.path = sys.path[::-1]

这将颠倒sys.path的顺序,意味着它将首先查找本地目录,而不是最后查找。
现在您可能认为这已经足够了,但是如果您试图在这里导入数学,python将在sys.modules中看到它,并且不会再尝试导入,所以首先

del sys.modules['math']

然后我们可以导入默认的数学模块

import math

最后清理系统路径

sys.path = sys.path[::-1]

现在我们可以得到我们需要的一切

>>>math.cos(10)
-0.8390715290764524
>>>local_math.f(10)
1000
gj3fmq9x

gj3fmq9x3#

根据官方文件:https://docs.python.org/3/library/imp.html
imp将在版本3.12中删除
自3.4版起已弃用,将在3.12版中删除:不建议使用imp模块,而建议使用importlib。
imp方法(不建议使用):

import imp
m = imp.load_source('math', './math.py')
m.foo()

对于importlib方法,代码“影响”最小的是:

def load_module(name, path):
    from importlib import util as importlib_util
    module_spec = importlib_util.spec_from_file_location(name, path)
    module = importlib_util.module_from_spec(module_spec)
    module_spec.loader.exec_module(module)
    return module

m = load_module('math', './math.py')
m.foo()

相关问题