Типичное использование, принципиальный анализ и эволюция -m в Python

Python

При использовании Python в командной строке он может принимать около 20 опций, синтаксис следующий:

python [-bBdEhiIOqsSuvVWx?] [-c command | -m module-name | script | - ] [args]

В этой статье мы хотим поговорить о более специальной опции «-m»:О его типичном использовании, принципиальном анализе и процессе развития и эволюции.

Во-первых, давайте воспользуемся "--help", чтобы увидеть его объяснение:

-m mod run library module as a script (terminates option list)

«мод» — это сокращение от «модуль», то есть содержимое после опции «-m» — это модуль (модуль), а его функция — запускать модуль как скрипт.

«завершает список опций» означает, что другие опции после «-m» не действуют, в этом отношении это то же самое, что и «-c», которые являются «опциями терминала». Они официально определены как «опции интерфейса», которые необходимо отличать от других общих опций или общих опций.

Пять типичных случаев использования параметра -m

Есть много сценариев использования опции -m в Python. Я думаю, вы могли их использовать или видели. Я хотел бы поделиться здесь пятью из них.

В Python3 простой HTTP-сервис можно реализовать всего одной строкой команды:

python -m http.server 8000

# 注:在 Python2 中是这样
python -m SimpleHTTPServer 8000

После выполнения откройте "http://localhost:8000", или открыть "http://local ip:8000" на других машинах в локальной сети, вы можете получить доступ к содержимому в исполнительном каталоге, например, следующая картинка - это содержимое моей локальной машины:

Точно так же нам нужна только одна строка команды «python -m pydoc -p xxx» для создания официальной справочной документации в формате HTML, к которой можно получить доступ в браузере.

Приведенная выше команда выполняет модуль pydoc, который запускает службу http на порту 9000 и открывает ее в браузере. Мои результаты следующие:

Его третье распространенное использование — выполнить команду отладки pdb «python -m pdb xxx.py», чтобы выполнить сценарий «xxx.py» в режиме отладки:

Четвертый, не менее полезный сценарий — использовать timeit для проверки времени выполнения небольшого фрагмента кода из командной строки. Следующие 3 фрагмента кода используют разные способы объединения числовой строки «0-1-2-...-99». Разницу в эффективности между ними можно увидеть интуитивно:

Наконец, часто упускают из виду сценарий: «python -m pip install xxx». Мы можем использовать «pip install xxx» по привычке или использовать «pip3 install xxx» для различения версий, короче говоря, не указывать его с «python -m» впереди. Но такой способ написания может быть проблематичным.

Так совпало, что в начале этого месяца (2019.11.01) основной разработчик Python,Первый руководящий комитетБретт Кэннон, один из пяти участников, написал в блоге "Why you should use "python -m pip" ", предложил способ использования "python -m pip" и подробно объяснил его.

Его основная идея заключается в том, что в средах, где существует несколько версий Python, эта нотация позволяет точно контролировать, где установлены сторонние библиотеки. Например, с помощью «python3.8 -m pip» вы можете явно указать версию 3.8 для установки, не путая ее с другими версиями.

(Расширенное чтение: в статье Бретта есть краткое изложение "Оказывается, я устанавливал библиотеку Python в неправильной позе!")

Анализ двух принципов опции -m

Прочитав предыдущие типичные употребления, стало ли вам любопытно:Как работает "-м"? Как это достигается?

Для «python -m name» объяснение одного предложения:Python будет получатьsys.path, найдите модуль или пакет с именем «name» (включая пакет пространства имен) и выполните его содержимое как модуль «__main__».

1. Для обычных модулей

Файл с суффиксом ".py" является модулем. При использовании после "-m" вам нужно использовать только имя модуля без написания суффикса, но предполагается, что имя модуля допустимо и не может быть написано на языке C. , написанный модуль.

После «-m», если это недопустимое имя модуля, будет сообщено об ошибке «Нет модуля с именем xxx».

Если это модуль с суффиксом, модуль будет импортирован первым, а затем может быть сообщено об ошибке: Ошибка при поиске спецификации модуля для «xxx.py» (AttributeError: модуль «xxx» не имеет атрибута «__path__».

Для общего модуля иногда эти два выражения кажутся эквивалентными:

Оба метода записи будут выполнять располагаемый модульный скрипт в качестве основной записи программы, то есть во время выполнения скрипт__name__Оба являются "__main__", что отличается от метода импорта.

Но его предпосылка заключается в том, что «test.py» существует в каталоге выполнения и есть только один «тестовый» модуль. Для этого примера, если он выполняется в другом каталоге, «python test.py», конечно, сообщит об ошибке «файл не найден», однако «python -m test» не сообщит об ошибке, поскольку интерпретатор проходитsys.pathВы можете найти «тестовый» модуль с тем же именем и выполнить:

Исходя из этой разницы, мы можем обобщить использование «-m»:Если известно имя модуля, но неизвестен путь к его файлу, то использование "-m" означает, что интерпретатор сам его найдет, а если найдет, то выполнит как скрипт.

Взяв предыдущий пример «python -m http.server 8000», мы также можем найти абсолютный путь к «серверному» модулю и выполнить его, хотя это станет громоздким.

Итак, в чем разница в реализации между методом "-m" и запуском скрипта напрямую?

  • При непосредственном запуске сценария это эквивалентно указанию полного пути к сценарию (будь то абсолютный путь или относительный путь), а интерпретатор основан намеханизм поиска файловой системы,Найдите скрипт и выполните
  • При использовании режима "-m" интерпретатор должен импортировать его вВсе пространства имен модулейНайдите, найдите путь к скрипту и выполните его. Для реализации этого процесса интерпретатор использует два модуля:pkgutilа такжеrunpy, первый используется для получения списка всех модулей, второй используется для поиска и выполнения скрипта в соответствии с именем модуля

2. Для модулей в упаковке

Если пакет должен быть выполнен после «-m», то интерпретатор найдет пакет после вышеупомянутого процесса поиска, а затем выполнит его подмодуль «__main__», то есть в каталоге пакета. Файл «__main__.py» должен быть реализованным.

Другими словами, предположим, что есть пакет с именем "pname", тогда«python -m pname» на самом деле эквивалентно «python -m pname.__main__».

Все еще возьмем предыдущий пример создания службы HTTP, «http» — это встроенный пакет в Python, и у него нет файла «__main__.py», поэтому при использовании метода «-m» для выполнения возникает ошибка будет сообщено: нет модуля с именем http.__main__; ' http' является пакетом и не может быть выполнен напрямую.

Для сравнения можно посмотреть на упомянутый выше pip, который тоже является пакетом Почему можно использовать метод "python -m pip"? Конечно, потому что у него есть файл «__main__.py»:

«python -m pip» фактически выполняет этот файл «__main__.py», который в основном используется как запись вызова, вызывая ядро ​​«pip._internal.main».

Поскольку пакет http не имеет унифицированного модуля ввода, он принимает метод «python -m package.module», в то время как пакет pip имеет унифицированный модуль ввода, поэтому добавляется файл «__main__.py», и, наконец, только нужно написать «python -m package», лаконично и интуитивно понятно.

Десять лет эволюции опции -m

Параметр -m был впервые представлен в Python 2.4 (2004 г.), который в то время был довольно ограниченным и мог работать только с обычными встроенными модулями (такими как pdb и profile).

Впоследствии известный разработчик Ник Коглан предложил «PEP 338 -- Executing modules as scripts》 выводит свою функцию на более высокий уровень. Этот PEP был предложен в 2004 году и окончательно реализован в версии 2.5 в 2006 году.

(Кроме того: Ник Каглан был одним из основных разработчиков и был одним из пяти членов Первого Руководящего комитета. Я помню, как читал материал, он был выбран в качестве основного разработчика в 2005 году, это время тесно соответствует -338)

Несколько основных точек этого PEP являются:

  • В сочетании с новым механизмом зондирования (новые перехватчики импорта) PEP-302 улучшена способность интерпретатора находить модули в пакете.
  • В сочетании с другими механизмами импорта (например,zipimportи замороженные модули), расширяя диапазон и точность, с которой интерпретатор может находить модули.
  • разработал новыйrunpy.run_module(modulename)Для достижения этой функции не модифицируйте интерпретатор CPYTHON, поэтому его удобно портировать на другие интерпретаторы.

На данный момент опция -m позволяет Python найти модули, приведенные в командной строке во всех пространствах имен.

В 2009 году в Python 3.1 можно было найти и запустить его подмодуль «__main__», просто указав имя пакета. В 2014 году параметр -m был расширен для поддержки пакетов с именами.

На данный момент, после десятилетия эволюции, опция -m стала полностью функциональной и полноценной.

Наконец, давайте закончим: опция -m может показаться неприметной, но это определенно одна из самых специальных опций, упрощающая использование встроенных модулей, стандартных пакетов и сторонних библиотек в командной строке. Используйте его, когда у вас есть возможность испытать приятные ощущения, которые он приносит.

использованная литература

docs.Python.org/3.7/using/… из…

да наркий.руб/почему-да-да ой…

Woohoo.Python.org/Dev/PEPs/PE…

blog.CSDN.net/See 3 small/Aretti…

Нет публики【Питон кот], в этом выпуске публикуются высококачественные серии статей, в том числе серия Meow Star Philosophy Cat, расширенная серия Python, серия рекомендаций по хорошим книгам, техническое письмо, высококачественные рекомендации и перевод на английский язык и т. д. Добро пожаловать на внимание.