2016-07-17 7 views
0

Я видел следующий код в парах проектов Python, в __main__.py. Может ли кто-нибудь объяснить цель? Конечно, он помещает каталог, содержащий __main__.py во главе sys.path, но почему? ? И почему тесты (__package__ is None and not hasattr(sys, 'frozen') Кроме того, в sys.path.insert, почему os.path.dirname вызывается дваждыНазначение некоторого кода шаблона в __main__.py

import sys 

if __package__ is None and not hasattr(sys, 'frozen'): 
    # direct call of __main__.py 
    import os.path 
    path = os.path.realpath(os.path.abspath(__file__)) 
    sys.path.insert(0, os.path.dirname(os.path.dirname(path))) 
+0

Пожалуйста, используйте [править], чтобы использовать соответствующие имена файлов. –

+1

. Чтобы установить проект Python, убедитесь, что правильный путь установлен из того, что я предполагаю, является каталогом сценариев в каталоге библиотеки, если они не используют упаковку Python. –

+0

Спасибо, сверчок, для редактирования моих имен с двойным подчеркиванием. Я не забуду использовать обратные тики в будущем, чтобы избежать символов форматирования. – cha

ответ

1

Тест на __package__ позволяет код должен выполняться, когда package/__main__.py было работать с командой, как или python package/ (именования файла непосредственно или присвоения имен путь к папке пакета), а не более нормальный способ запуска основного модуля пакета python -m package. Другая проверка (для sys.frozen) проверяет, был ли пакет упакован с чем-то вроде py2exe в один файл, а не в обычную файловую систему.

Что делает код, помещает родительскую папку пакета в sys.path. То есть, если __main__.py находится по адресу /some/path/to/package/__main__.py, код будет помещен /some/path/to в sys.path. Каждый вызов dirname снимает один элемент с правой стороны пути ("/some/path/to/package/__main__.py" =>"/some/path/to/package" =>"/some/path/to").

+0

Спасибо. Теперь тест имеет смысл. Я не думал о том, как вы можете запустить '__main __. Py'. – cha

+0

Могу ли я задать связанный с этим вопрос: если вы структурировали свое приложение как исполняемый пакет, то есть, если у него есть '__main __. Py' и' __init __. Py', то в '__main __. Py' у вас будет канонический "if __name __ == '__main__'", где вы действительно запускаете приложение. Я бы не поставил там очень много кода, возможно, одну строку для вызова «реальной» основной функции. Но вы бы определили эту настоящую главную функцию прямо в '__main __. Py' или создали для нее новый файл модуля? Очевидно, вы могли бы разместить его там, где захотите, но что считается «наилучшей практикой» относительно местоположения реальной основной функции? – cha

2

os.path.dirname(os.path.dirname(path)) - Получает внучатая родительский каталог (каталог, содержащий каталог данной path переменной);? Это время добавлено к PATH переменной системы

os.path.realpath(os.path.abspath(__file__)) -.. Возвращает realpath (устраняющее символическое связывание) абсолютного пути бегущего файла

с помощью этого метода, р Теперь roject может выполнять двоичные файлы, которые включены в этот каталог grandparent без необходимости префикса бинарного исполняемого файла.

Sidenote: Без контекста того, где вы видите этот код, трудно дать больше ответа о том, почему его использовали.

+0

Технически это немного избыточно, поскольку realpath и abspath должны выполнять аналогичные функции. Фактически, realpath для модуля 'posixpath' вызывает abspath, а для' ntpath' realpath - это псевдоним abspath. В противном случае, +1. –

+0

@ Александр Хушаг. Конечно, я просто объяснял эту функцию, а не реализацию. –

+1

Ярмарка. Хотя относительно того, что многие скрипты используют каталог «scripts» (который может быть любым именем), а затем иметь библиотечный каталог. Использование двух dirnames затем будет разрешено в основной каталог, поэтому импорт из библиотеки может быть разрешен без стандартной упаковки Python. Это отлично подходит для автономных приложений, которые можно установить с помощью setuptools или без него. (Не 100%, но это довольно распространенный вариант использования). –