os.path
работает забавно. Похоже, это os
должен быть пакет с подмодулем path
, но на самом деле os
это обычный модуль, который творит чудеса с sys.modules
инъекцией os.path
. Вот что происходит:
Когда Python запускается, он загружает кучу модулей в sys.modules
. Они не привязаны к каким-либо именам в вашем скрипте, но вы можете получить доступ к уже созданным модулям, когда вы каким-либо образом их импортируете.
sys.modules
это диктовка, в которой кэшируются модули. Когда вы импортируете модуль, если он уже был куда-то импортирован, он получает экземпляр, хранящийся в sys.modules
.
os
входит в число модулей, загружаемых при запуске Python. Он назначает свой path
атрибут специфичному для ОС модулю пути.
Он внедряет sys.modules['os.path'] = path
так, чтобы вы могли " import os.path
" делать " ", как если бы это был подмодуль.
Я склонен думать , os.path
как модуль я хочу использовать , а не вещь в os
модуле , так что даже если это не очень подмодуль пакета называется os
, я импортировать его вроде как это один и я всегда делаюimport os.path
. Это согласуется с тем, как os.path
документируется.
Между прочим, такая структура, я думаю, приводит к тому, что многие программисты Python на ранних этапах заблуждаются по поводу модулей, пакетов и организации кода. Это действительно по двум причинам
Если вы думаете о os
пакете и знаете, что можете делать import os
и иметь доступ к подмодулю os.path
, вы можете быть удивлены позже, когда не сможете сделать import twisted
и автоматически получить доступ twisted.spread
без его импорта.
Сбивает с толку, что os.name
это обычная вещь, строка, а os.path
это модуль. Я всегда структурирую свои пакеты с пустыми __init__.py
файлами, чтобы на одном уровне у меня всегда был один тип вещей: модуль / пакет или другие вещи. Этот подход используется в нескольких крупных проектах Python, направленных на создание более структурированного кода.
import os.path
сам и думаю, что это более приятный способ. Под «Это согласуется с тем, как документируется os.path» я имел в виду, что ему дается отдельная страница в документации по адресу docs.python.org/library/os.path.html .os.py
действительно впрыскиваетsys.modules['os.path']
. Вот почему наfrom os.path import something
самом деле работает. Мне было любопытно, когда это было введено, и я проверил источник. Интересный факт: это с 1999 года, впервые включенное в Python 1.5.2. Оригинальный коммит здесь .Согласно PEP-20 Тима Петерса, «Явное лучше, чем неявное» и «Читаемость имеет значение». Если все, что вам нужно от
os
модуля, находится нижеos.path
,import os.path
будет более явным и пусть другие знают, что вас действительно волнует.Точно так же PEP-20 также говорит: «Простое лучше, чем сложное», поэтому, если вам также нужны вещи, которые находятся под более общим
os
зонтом,import os
будет предпочтительнее.источник
import os
на самом деле быть «простым» в каком-либо значимом смысле. Просто! = Коротко.import os
и этоimport os.path
глупо, если вам, например, нужноos.getcwd()
иos.path.isfile()
Окончательный ответ:
import os
и пользуйтесьos.path
. не делайтеimport os.path
прямо.Из документации самого модуля:
>>> import os >>> help(os.path) ... Instead of importing this module directly, import os and refer to this module as os.path. The "os.path" name is an alias for this module on Posix systems; on other systems (e.g. Mac, Windows), os.path provides the same operations in a manner specific to that platform, and is an alias to another module (e.g. macpath, ntpath). ...
источник
os.path
модуля, которого не существует, а дляposixpath
."Instead of importing this module directly, import os and refer to this module as os.path."
находится вposixpath.py
(илиmacpath.py
иntpath.py
т. Д.). Я почти уверен, что они означают, что не следуетimport posixpath
(что работает), а лучше импортировать модуль черезos
для лучшей переносимости. Я не думаю , что они намерены дать рекомендации в отношении тогоimport os
илиimport os.path
предпочтителен.Что интересно, импорт os.path импортирует все файлы os. попробуйте следующее в интерактивной подсказке:
import os.path dir(os)
Результат будет таким же, как если бы вы только что импортировали os. Это связано с тем, что os.path будет ссылаться на другой модуль в зависимости от того, какая у вас операционная система, поэтому python будет импортировать os, чтобы определить, какой модуль загружать для пути.
Справка
С некоторыми модулями высказывание
import foo
не раскрываетсяfoo.bar
, поэтому я предполагаю, что это действительно зависит от дизайна конкретного модуля.В общем, простой импорт явных модулей, которые вам нужны, должен быть немного быстрее. На моей машине:
import os.path
:7.54285810068e-06
секундыimport os
:9.21904878972e-06
секундыЭти времена достаточно близки, чтобы ими можно было пренебречь. Ваша программа может нуждаться в использовании других модулей
os
либо сейчас, либо позже, поэтому обычно имеет смысл просто пожертвовать двумя микросекундами и использовать их,import os
чтобы избежать этой ошибки в более позднее время. Я обычно поддерживаю простой импорт ОС в целом, но могу понять, почему некоторые предпочлиimport os.path
бы технически быть более эффективными и донести до читателей кода, что это единственная частьos
модуля, которую нужно будет использовать. По сути, в моем понимании это сводится к вопросу о стиле.источник
from os import path
вызовет path еще быстрее, если проблема в скорости.Здесь работает здравый смысл:
os
это модуль, иos.path
это тоже модуль. Так что просто импортируйте модуль, который хотите использовать:Если вы хотите использовать функции
os
модуля, импортируйтеos
.Если вы хотите использовать функции
os.path
модуля, импортируйтеos.path
.Если вы хотите использовать функции обоих модулей, импортируйте оба модуля:
import os import os.path
Для справки:
Lib / idlelib / rpc.py использует
os
и импортируетos
.Lib / idlelib / idle.py использует
os.path
и импортируетos.path
.Lib / surepip / init .py использует оба и импортирует оба.
источник
Не удалось найти какой-либо исчерпывающей ссылки, но я вижу, что пример кода для os.walk использует os.path, но импортирует только os
источник