Использование абсолютного импорта и обработка конфликтов имен относительных модулей в python
Я действительно надеюсь, что это простой случай, когда мне не хватает понимания сложных механизмов импорта Python2. У меня есть следующая настройка:
$> ls -ltr pypackage1
total 3
-rw-r--r-- 1 pelson pelson 0 Aug 17 19:20 io.py
-rw-r--r-- 1 pelson pelson 0 Aug 17 19:20 __init__.py
-rw-r--r-- 1 pelson pelson 57 Aug 17 19:22 code.py
$> cat pypackage1/code.py
from __future__ import absolute_import
import zipfile
т. е. у меня нет ничего, кроме пакета заглушки с пустым __init__.py
и io.py
, и 2 строки .
Я могу импортировать pypackage1
:
$> python -c "import pypackage1.code"
но я не могу запустить :
$> python pypackage1/code.py
Traceback (most recent call last):
File "pypackage1/code.py", line 3, in <module>
import zipfile
File "python2.7/zipfile.py", line 462, in <module>
class ZipExtFile(io.BufferedIOBase):
AttributeError: 'module' object has no attribute 'BufferedIOBase'
очевидно, что проблема связана с собирание мой родственник модуль IO над зданием io
модуль, но я думал, что мой from __future__ import absolute_import
исправил бы это.
заранее спасибо за любую помощь,
3 ответов
это правильное поведение. Если вы хотите исправить ошибку, просто не запускайте ее изнутри пакета.
когда вы запускаете скрипт, который находится внутри пакета, python не интерпретирует этот каталог как пакет, добавляя таким образом рабочий каталог в PYTHONPATH
.
Вот почему io
модуль импортирован zipfile
модуль-это ваш io
модуль, а не внутри стандартной библиотеки.
Я бы рекомендовал создать простой сценарий запуска вне вашего пакет (или в bin/scripts
папка), и запустите это. Этот скрипт может просто содержать что-то вроде:
from pypackage1 import code
code.main()
альтернативой этому является сообщить интерпретатору python, что файл, который вы хотите выполнить, является частью модуля. Вы можете сделать это с помощью командная строка. В вашем случае вам придется делать:
python -m pypackage1.code
обратите внимание, что аргумент -m
должен быть имя модуля, а не имя файла.
одним из решений было бы поставить from __future__ import absolute_import
на zipfile.py
модуль. Хотя код модуль использует абсолютный импорт,zip-файл модуль не.
другой вариант-не запускать из каталога пакета. Вероятно, вы не должны запускать интерпретатор из каталога пакетов.
структура файла:
test.py
mylib/__init__.py
mylib/__collections.py
mylib/collections.py
mylib/mymod.py
это решение позволяет:
- test.py чтобы вызвать оба _ _ builtin__.сборники и mylib.сборники
- mymod.py чтобы вызвать вышеизложенное, как когда он работает как часть библиотеки и когда он запускается автономно (например, для тестового кода)
In test.py:
from collections import deque
from mylib.collections import mydict
In mylib/__init__.py:
from __future__ import absolute_import
from . import collections
from . import mymod
In mylib/__collections.py:
class MyDict (dict):
pass
In mylib/collections.py:
from __collections import *
In mylib/mymod.py:
from __future__ import absolute_import
from collections import deque
try:
# Module running as part of mylib
from .collections import MyDict
except ValueError:
# Module running independently
from __collections import MyDict
вышеуказанное работает с Python >=2.5. Python 3 не нуждается в строках "from _ _ future_ _ import absolute_import".