2010-04-27 1 views
103

Согласно official documentation, os.path является модулем. Таким образом, каков предпочтительный способ его импорта?Должен ли я использовать `import os.path` или` import os`?

# Should I always import it explicitly? 
import os.path 

Или ...

# Is importing os enough? 
import os 

Пожалуйста, НЕ отвечать "импортирования os работает для меня". Я знаю, это работает для меня тоже прямо сейчас (с Python 2.6). То, что я хочу знать, - это официальная рекомендация по этому вопросу. Итак, если вы ответите на этот вопрос, пожалуйста, напишите ваши отзывы.

ответ

121

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 программистов о модулях и пакетов и организации кода, я думаю. Это действительно по двум причинам

  1. Если вы думаете о os как пакет и знаете, что вы можете сделать import os и иметь доступ к субмодулю os.path, вы можете быть удивлены позже, когда вы не можете сделать import twisted и автоматически доступ twisted.spread без импорта.

  2. Сложно предположить, что os.name - это обычная вещь, строка и os.path - это модуль. Я всегда структурирую свои пакеты с пустыми __init__.py файлами, так что на том же уровне у меня всегда есть один тип вещей: модуль/пакет или другое. Несколько больших проектов Python используют этот подход, который, как правило, создает более структурированный код.

+0

Отличный, очень информативный ответ! Поздравления! Несмотря на то, что он напрямую не отвечает на вопрос, у него много полезных деталей. Но не могли бы вы подробно остановиться на «Это согласуется с тем, как os.path документирован»? Как сказал Крис Хулан, пример os.walk() импортирует только os вместо os.path. –

+3

@Denilson, он включает прямой ответ: я всегда сам «импортирую os.path» и думаю, что это лучше. В разделе «Это согласуется с тем, как os.path документирован». Я имел в виду, что ему предоставляется собственная страница в документации по адресу http://docs.python.org/library/os.path.html. –

+0

Почему? Почему так делается? – user1712447

6

Интересно, что импорт os.path будет импортировать все os. в интерактивной программе:

import os.path 
dir(os) 

Результат будет таким же, как если бы вы только что импортировали os. Это связано с тем, что os.path будет ссылаться на другой модуль, на основе которого у вас есть операционная система, поэтому python будет импортировать os, чтобы определить, какой модуль загружается для пути.

reference

С некоторыми модулями, говоря import foo не подвергнет foo.bar, так что я предполагаю, что это действительно зависит от конструкции конкретного модуля.

В общем, просто импортировать явные модули, которые вам нужны, должны быть немного быстрее. На моей машине:

import os.path:7.54285810068e-06 секунд

import os:9.21904878972e-06 секунд

Эти времена достаточно близко, чтобы быть довольно незначительным. Возможно, вашей программе придется использовать другие модули от os либо сейчас, либо позже, поэтому обычно имеет смысл просто пожертвовать двумя микросекундами и использовать import os, чтобы избежать этой ошибки позднее. Я обычно предпочитаю импортировать ОС в целом, но вижу, почему некоторые предпочитают import os.path технически быть более эффективными и передавать читателям код, который является единственной частью модуля os, который необходимо будет использовать. Это, по сути, сводится к вопросу стиля в моем сознании.

+2

'из ОС импорта path' будет делать звонки на пути еще быстрее если скорость является проблемой. –

+0

Будучи pythonic, явное лучше, чем неявное право? На самом деле я думаю, что это действительно вызов пользователя, независимо от того, использует ли пользователь только os.path или несколько модулей внутри os. Может быть, один метод больше соответствует вашей философии над другой? –

+14

Сроки это некоторая предварительная преждевременная оптимизация, которую я когда-либо видел. Это никогда не было «чьим-либо» узким местом, и время здесь не имеет значения, как кто-то должен кодировать. –

4

Не удалось найти окончательный ссылку, но я вижу, что пример кода для os.walk использует os.path но только импортирует ОС

27

Согласно PEP-20 Тим Питерс, «Явное лучше, чем неявное» и «читаемости рассчитывает». Если все, что вам нужно от модуля os, находится под os.path, то import os.path будет более явным и позволит другим узнать, что вам действительно нужно.

Аналогичным образом, PEP-20 также говорит, что «Простой лучше, чем сложный», поэтому, если вам также нужны вещи, которые находятся под более общим зонтиком os, то предпочтение будет отдаваться import os.

+2

Я не вижу, как 'import os' действительно о том, чтобы быть« простым »любым значимым способом. Простой! = Короткий. –

+10

Я больше пытался указать, что 'import os' ** и **' import os.path' является глупым, если вы, например. need 'os.getcwd()' и 'os.path.isfile()' –

14

Definitive Ответ: 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). 
... 
+7

Обратите внимание, что это не документы для модуля 'os.path', который не существует, а для' posixpath'. – wRAR

+8

Это совсем не так, как я думаю, что docstring предназначается для интерпретации, хотя это довольно обманчиво. Имейте в виду, что предложение '' Вместо непосредственного импорта этого модуля import os и ссылайтесь на этот модуль как os.path. "' Находится в 'posixpath.py' (или' macpath.py', 'ntpath.py 'и т. д.). Я довольно уверен, что они подразумевают, что нельзя «импортировать posixpath» (который работает), а скорее импортировать модуль через 'os' для лучшей переносимости. Я не думаю, что они намереваются дать рекомендацию относительно того, предпочтительнее ли «импорт os» или «import os.path». – flornquake

+1

Я согласен с большинством комментариев @flornquake, но не согласен с последним предложением. Оба posixpath.py и ntpath.py говорят «import os и ссылаются на этот модуль как os.path». Они не говорят «import os.path и ссылаются на этот модуль как os.path». macpath.py не имеет ничего общего. –

0

Я согласен с Майком

Я думаю

import os прекрасно.

Вы только тогда должны упомянуть детали, как этот

os.path() 

или если вы вызываете модуль в модуле

os.path.exists() 
Смежные вопросы