модуль импорта с таким же именем, как встроенный модуль в Python 3 - PullRequest
0 голосов
/ 09 февраля 2019

Я сталкиваюсь с подобной проблемой, которую можно упростить следующим образом:

Например, у меня есть файловая структура:

----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. Если я только хочу импортировать модуль math.py по пути folder, имя которого совпадает с именем встроенного модуля, что мне делать?

  2. Если в main.py я хочу использовать и math.f(x), определенные в моем math.py и встроенном math.acos(x), что я должен делать?

PS: Я сталкиваюсь с подобной проблемой, поскольку у меня есть длинные коды, написанные кем-то десять лет назад.В то время не было встроенного модуля с таким именем (на самом деле это не модуль math. Я просто упростил задачу с помощью вышеуказанного вопроса).И функции этого модуля были использованы во многих местах.Поэтому изменить имя модуля практически невозможно, так как в этом случае мне нужно тщательно изменить все сайты module.function().

Ответы [ 2 ]

0 голосов
/ 09 февраля 2019

нырнул в кроличью нору, но здесь мы идем.В качестве отказа от ответственности, как сказал Джек, именование модулей после встроенных команд является очень плохой практикой, и это легче сделать, используя imp, как он предложил.

Причина, по которой у вас проблемы, связана с взаимодействием нескольких вещей.Когда вы набираете

import math

, то, что делает ваш питон, это смотрит на sys.path.Он проверит все местоположения в sys.path для модуля с именем math и импортирует первый найденный модуль.В вашем случае он сначала находит ваш локальный математический модуль.После завершения импорта он добавляет его в sys.modules, но мы вернемся к этому.

Поскольку вы хотите использовать оба, сначала вы можете импортировать свою локальную математику, как у вас есть.Я бы предложил импортировать его под другим именем, чтобы оно было отдельным.

from . import math as local_math

После этого нам нужно связываться с нашим sys.path, чтобы найти встроенную математику

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

Это меняет порядок sys.path, то есть он будет выглядеть в вашемсначала локальный каталог, а не последний.

Теперь вы можете подумать, что этого достаточно, но если вы попытаетесь импортировать математику здесь, python увидит ее в sys.modules и не будет пытаться импортировать снова, поэтому сначала

del sys.modules['math']

Затем мы можем импортировать математический модуль по умолчанию

import math

и, наконец, очистить наш sys.path

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

, теперь у нас есть доступ ко всему, что нам нужно

>>>math.cos(10)
-0.8390715290764524
>>>local_math.f(10)
1000
0 голосов
/ 09 февраля 2019

Это довольно плохая практика называть ваши модули в честь встроенных модулей.Я бы порекомендовал назвать ваш math.py как-нибудь еще.

При этом вы можете импортировать его, используя путь с imp:

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