Это - проблема, которую я только видел в Windows.
системы Unixish не делают привычку к тому, чтобы вынуждать общие библиотеки связаться с различными версиями той же библиотеки в рамках той же программы, и все загруженные символы видимы глобально. Это означает, что, если объект выделен в одной части кода и удален в другом, оба используют ту же системную библиотеку, чтобы сделать это.
я должен сказать, этот проблемный Windows создает с его различным DLLs во время выполнения C, является действительно раздражающим и неестественным программисту C. Посмотрите на библиотеку C; это имеет функции как strdup, который malloc строка и ожидают, что программист назовет свободным () на нем. Но сделайте то же самое в своей собственной библиотеке по Windows и просто ожидайте взрыва. Необходимо будет ожидать также, потому что этого не произойдет во время разработки, но только после предоставления скомпилированного DLL некоторому другому плохому соку.
После того, как я немного поигрался с этим, я понял, как его настроить, и ради определенности я не буду использовать названия foo bar. Каталог моего проекта настроен как ...
tools/
core/
object_editor/
# files that need to use ntlib.py
editor.py # see example at bottom
__init__.py
state_editor/
# files that need to use ntlib.py
__init__.py
ntlib.py
__init__.py # core is the top level package
LICENSE
state_editor.py # equivalent to main.py for the state editor
object_editor.py # equivalent to main.py for the object editor
Строка в object_editor.py
выглядит как ...
from core.object_editor import editor
Строка в editor.py
выглядит как ...
from .. import ntlib
или альтернативно
from core import ntlib
Ключ в том, что в примере, который я привел в вопросе, «основной» скрипт запускался из пакета. После того, как я переместил его, создал специальный пакет (core
) и переместил библиотеку, которую редакторы хотели бы поделиться (ntlib
) в этом пакете, все было в порядке вещей.
хотя длинных «вещей» нет в вашем PATH PATH, у вас нет выбора, кроме как добавить путь.
Если вы знаете уровень вашего script.py из того, что вы можете сделать, например:
import sys
import os
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..'))
Я использую Python 3.4.2 в Windows 7 и оторвал себе волосы.
При выполнении любого из них:
python -m unittest python -m unittest Discover
... Я бы получил 'Попытка относительного импорта за пределы пакета верхнего уровня 'ошибка.
Для меня решением было опустить ".." в моем [test_stock.py]. Строка была: от .. запаса импорта запасов
Изменил его на: от запаса импорта запасов
.. и он работает.
Структура папок:
C:\
|
+-- stock_alerter
|
+-- __init__.py
+-- stock.py
|
\-- tests
|
+-- __init__.py
\-- test_stock.py
import ..foo..stuff.mylib
должно быть в порядке
EDIT снял расширение
Из PEP видно, что вы не можете использовать относительный импорт для импорта файла, который не был упакован.
Таким образом, вам нужно будет добавить __init__.py
к вещам и изменить ваш импорт на что-то вроде from .mylib import *
Однако, похоже, PEP не позволяет хранить mylib упакованным в модуле. Так что вам может потребоваться изменить способ вызова функций библиотеки.
Другая альтернатива - переместить mylib в подпакет и импортировать его как from .libpackage import mylib
Если вы работаете в Linux или похожем * nix, вы можете взломать это с помощью символических ссылок.
stuff/
mylib.py
foo.py // equivalent of main.py in above
foo/
script.py
mylib.py -> ../mylib.py
foo2/
script2.py
mylib.py -> ../mylib.py
Это, вероятно, не очень хорошая схема для подражания.
В моем случае я выбрал это, потому что у меня было несколько исполняемых файлов, зависящих от одной и той же библиотеки, которые нужно было поместить в отдельные каталоги.
Реализация новых исполняемых тестов не должна требовать от автора тестов глубокого понимания импорта python.
tests/
common/
commonlib.py
test1/
executable1.py
executable2.py
commonlib.py -> ../common/commonlib.py
test2/
executable1.py
executable2.py
commonlib.py -> ../common/commonlib.py