У меня есть проект python с файлом конфигурации в корне проекта. К файлу конфигурации нужно обращаться в нескольких разных файлах в рамках проекта.
Так что это выглядит примерно так: <ROOT>/configuration.conf
<ROOT>/A/a.py
, <ROOT>/A/B/b.py
(если б, a.py доступ к файлу конфигурации).
Какой лучший / самый простой способ получить путь к корню проекта и файлу конфигурации независимо от того, в каком файле внутри проекта я нахожусь? т.е. без использования ../../
? Можно предположить, что мы знаем имя корня проекта.
<ROOT>/__init__.py
существует?os.path.expanduser('~/.myproject/myproject.conf')
. Работает в Unix и Windows.Ответы:
Вы можете сделать это так, как это делает Django: определить переменную для корневого каталога проекта из файла, который находится на верхнем уровне проекта. Например, если так выглядит структура вашего проекта:
В
definitions.py
можно определить (это требуетсяimport os
):Таким образом, зная Project Root , вы можете создать переменную, которая указывает на расположение конфигурации (это может быть определено где угодно, но логичным местом было бы поместить ее в место, где определены константы - например
definitions.py
):Затем, вы можете легко получить доступ к постоянной (в любой из других файлов) с оператором импорта (например , в
utils.py
):from definitions import CONFIG_PATH
.источник
__init__.py
файл в корневой каталог проекта? Это должно быть правильно? Я только начал с Python и не уверен в лучших практиках. Спасибо.__init__.py
не будет необходимости, поскольку этот файл требуется только при определении пакетов: Эти__init__.py
файлы необходимы , чтобы Python лечить каталоги как содержащие пакеты; это сделано для того, чтобы каталоги с общим именем, таким как строка, случайно не скрывали допустимые модули, которые появляются позже на пути поиска модулей. В простейшем случае это__init__.py
может быть просто пустой файл, но он также может выполнять код инициализации для пакета или устанавливать__all__
переменную, как описано ниже. См .: docs.python.org/3/tutorial/modules.html#packages__init.py__
корневой пакет. Это сэкономило бы создание другого файла, а также позволило бы более удобный синтаксисfrom root_pack import ROOT_DIR, CONFIG_PATH
.__init__.py
пустым, но это не совсем так (в конце концов, это соглашение). Смотрите это для более: stackoverflow.com/questions/2361124/using-init-pyos.path.abspath
звонит строку,'__file__'
. Напомним, что__file__
на самом деле это атрибут импорта, определенный для модулей Python. В этом случае__file__
вернет путь, с которого загружен модуль. Подробнее здесь (см. Раздел о модулях): docs.python.org/3/reference/datamodel.htmlДругие ответы советуют использовать файл на верхнем уровне проекта. В этом нет необходимости, если вы используете
pathlib.Path
иparent
(Python 3.4 и выше). Рассмотрим следующую структуру каталогов, в которой опущены все файлы, кромеREADME.md
иutils.py
.В
utils.py
мы определяем следующую функцию.В любом модуле проекта мы теперь можем получить корень проекта следующим образом.
Преимущества : Любой модуль, вызовы которого
get_project_root
можно перемещать без изменения поведения программы. Только когда модульutils.py
перемещается, мы должны обновлятьget_project_root
и импортировать (для автоматизации этого можно использовать инструменты рефакторинга).источник
Все предыдущие решения кажутся слишком сложными для того, что вам нужно, и часто у меня не работали. Следующая однострочная команда делает то, что вы хотите:
источник
Чтобы получить путь к "корневому" модулю, вы можете использовать:
Но что более интересно, если у вас есть конфигурационный «объект» в самом верхнем модуле, вы можете-прочитать- из него следующим образом:
источник
os
по умолчанию не доступны. Нужно импортироватьos
. Таким образом, добавление строкиimport os
сделает ответ более полным.python3 -m topmodule.submodule.script
выдаст/path/to/topmodule/submodule
вместо/path/to/topmodule
.Стандартный способ добиться этого - использовать
pkg_resources
модуль, который является частьюsetuptools
пакета.setuptools
используется для создания устанавливаемого пакета Python.Вы можете использовать
pkg_resources
для возврата содержимого желаемого файла в виде строки, и вы можете использоватьpkg_resources
для получения фактического пути к желаемому файлу в вашей системе.Допустим, у вас есть пакет с именем
stackoverflow
.Теперь предположим, что вы хотите получить доступ к файлу Rush из модуля
app.run
. Используйте,pkg_resources.resouces_filename
чтобы получить путь к Рашу иpkg_resources.resource_string
получить содержимое Раша; Таким образом:Выход:
Это работает для всех пакетов в вашем пути Python. Итак, если вы хотите знать, где он
lxml.etree
находится в вашей системе:вывод:
Дело в том, что вы можете использовать этот стандартный метод для доступа к файлам, установленным в вашей системе (например, pip install xxx или yum -y install python-xxx) и файлам, которые находятся в модуле, над которым вы сейчас работаете.
источник
Пытаться:
источник
Код ниже Возвращает путь до корня вашего проекта
источник
Я тоже боролся с этой проблемой, пока не пришел к этому решению. На мой взгляд, это самое чистое решение.
В вашем setup.py добавьте "пакеты"
В вашем python_script.py
источник
python3 setup.py install
ней больше не указывали на папку с исходным кодом, а на яйцо внутри~./virtualenv/..../app.egg
. Поэтому мне пришлось включить файл конфигурации в установку пакета.Просто пример: я хочу запустить runio.py из helper1.py
Пример дерева проекта:
Получите рут проекта:
Путь сборки к скрипту:
источник
Это сработало для меня, используя стандартный проект PyCharm с моей виртуальной средой (venv) в корневом каталоге проекта.
Код ниже не самый красивый, но последовательно получает корень проекта. Он возвращает полный путь к каталогу venv из
VIRTUAL_ENV
переменной среды, например/Users/NAME/documents/PROJECT/venv
Затем он разделяет путь последним
/
, давая массив из двух элементов. Первым элементом будет путь к проекту, например/Users/NAME/documents/PROJECT
источник
Недавно я пытался сделать что-то подобное, и я нашел эти ответы неадекватными для моих вариантов использования (распределенная библиотека, которая должна определять корень проекта). В основном я боролся с разными средами и платформами, но до сих пор не нашел чего-то совершенно универсального.
Используйте локальный код для проекта
Я видел, как этот пример упоминался и использовался в нескольких местах, в Django и т. Д.
Каким бы простым это ни было, он работает только тогда, когда файл, в котором находится фрагмент, фактически является частью проекта. Мы получаем не каталог проекта, а каталог сниппета.
Точно так же подход sys.modules не работает при вызове извне точки входа приложения, в частности, я заметил, что дочерний поток не может определить это без обратной связи с « основным » модулем. Я явно поместил импорт внутри функции, чтобы продемонстрировать импорт из дочернего потока, перемещение его на верхний уровень app.py исправит это.
app.py
settings.py
При запуске этой программы возникает ошибка атрибута:
... следовательно, решение на основе потоков
Независимо от местоположения
Использование той же структуры приложения, что и раньше, но изменение settings.py
Разбивка на части: сначала мы хотим точно найти идентификатор основного потока. В Python3.4 + библиотека потоковой передачи,
threading.main_thread()
однако, не использует версии 3.4+, поэтому мы ищем все потоки в поисках основного потока, сохраняя его идентификатор. Если основной поток уже завершился, он не будет указан в спискеthreading.enumerate()
. ВRuntimeError()
этом случае мы поднимаем a, пока не найду лучшее решение.Затем мы находим самый первый кадр стека основного потока. Используя специальную функцию cPython,
sys._current_frames()
мы получаем словарь текущего кадра стека каждого потока. Затем, используя,inspect.getouterframes()
мы можем получить весь стек для основного потока и самого первого кадра. current_main_frame = sys._current_frames () [main_id] base_frame = inspect.getouterframes (current_main_frame) [- 1] Наконец,inspect.getouterframes()
необходимо учесть различия между реализациями Windows и Linux . Использование очищенного имени файлаos.path.abspath()
иos.path.dirname()
очистка.До сих пор я тестировал это на Python2.7 и 3.6 в Windows, а также на Python3.4 на WSL.
источник
Если вы работаете с anaconda-project, вы можете запросить PROJECT_ROOT из переменной среды -> os.getenv ('PROJECT_ROOT'). Это работает только в том случае, если скрипт выполняется через запуск проекта anaconda.
Если вы не хотите, чтобы ваш скрипт запускался anaconda-project, вы можете запросить абсолютный путь к исполняемому двоичному файлу интерпретатора Python, который вы используете, и извлечь строку пути до каталога envs exclusiv. Например: интерпретатор python моего conda env находится по адресу:
Это работает только с conda-project с фиксированной структурой проекта anaconda-project.
источник
Я использовал метод ../, чтобы получить текущий путь к проекту.
Пример: Project1 - D: \ projects
ЦСИ
ConfigurationFiles
configuration.cfg
Path = "../ SRC / ConfigurationFiles / configuration.cfg"
источник
На момент написания ни одно из других решений не было самодостаточным. Они зависят либо от переменной среды, либо от положения модуля в структуре пакета. Главный ответ с решением «Django» становится жертвой последнего, поскольку требует относительного импорта. Он также имеет недостаток, заключающийся в необходимости изменения модуля на верхнем уровне.
Это должен быть правильный подход для поиска пути к каталогу пакета верхнего уровня:
Он работает, беря первый компонент в пунктирной строке, содержащейся в,
__name__
и используя его в качестве ключа, вsys.modules
котором возвращается объект модуля пакета верхнего уровня. Его__file__
атрибут содержит путь , который мы хотим после обрезки с/__init__.py
помощьюos.path.dirname()
.Это решение является самодостаточным. Он работает где угодно в любом модуле пакета, в том числе в
__init__.py
файле верхнего уровня .источник
Мне пришлось реализовать собственное решение, потому что это не так просто, как вы думаете. Мое решение основано на проверке трассировки стека (
inspect.stack()
) +sys.path
и работает нормально независимо от расположения модуля python, в котором вызывается функция, и интерпретатора (я пробовал запускать его в PyCharm, в оболочке поэзии и других ... ). Это полная реализация с комментариями:источник
Здесь много ответов, но я не смог найти чего-то простого, охватывающего все случаи, поэтому позвольте мне также предложить свое решение:
источник