Каковы хорошие практические правила для импорта Python? - PullRequest
71 голосов
/ 11 октября 2008

Меня немного смущает множество способов, которыми вы можете импортировать модули в Python.

import X
import X as Y
from A import B

Я читал о области видимости и пространствах имен, но мне хотелось бы получить несколько практических советов о том, какая стратегия лучше, при каких обстоятельствах и почему. Должен ли импорт происходить на уровне модуля или на уровне метода / функции? В __init__.py или в самом коде модуля?

На мой вопрос действительно нет ответа " Пакеты Python - импорт по классам, а не по файлу ", хотя он, очевидно, связан

Ответы [ 10 ]

63 голосов
/ 11 октября 2008

В производственном коде нашей компании мы стараемся придерживаться следующих правил.

Мы помещаем импорт в начало файла, сразу после строки документа основного файла, например ::100100

"""
Registry related functionality.
"""
import wx
# ...

Теперь, если мы импортируем класс, который является одним из немногих в импортируемом модуле, мы импортируем имя напрямую, так что в коде нам нужно использовать только последнюю часть, например:

from RegistryController import RegistryController
from ui.windows.lists import ListCtrl, DynamicListCtrl

Однако существуют модули, которые содержат десятки классов, например, список всех возможных исключений. Затем мы импортируем сам модуль и ссылаемся на него в коде:

from main.core import Exceptions
# ...
raise Exceptions.FileNotFound()

Мы используем import X as Y настолько редко, насколько это возможно, потому что это затрудняет поиск использования определенного модуля или класса. Однако иногда вам придется использовать его, если вы хотите импортировать два класса, которые имеют одинаковые имена, но существуют в разных модулях, например ::

.
from Queue import Queue
from main.core.MessageQueue import Queue as MessageQueue

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

34 голосов
/ 11 октября 2008

Позвольте мне вставить часть разговора в список рассылки django-dev, начатый Гвидо ван Россумом:

[...] Например, это часть руководств по стилю Google Python [1], что все import должен импортировать модуль, а не класс или функцию из этого модуль. Есть намного больше классов и функций, чем есть модули, поэтому вспомнить, откуда происходит конкретная вещь, много проще, если перед ним стоит имя модуля. Часто несколько модулей случается, чтобы определить вещи с тем же именем - так читатель кода не нужно возвращаться к началу файла, чтобы увидеть, из какого Модуль с заданным именем импортируется.

Источник: http://groups.google.com/group/django-developers/browse_thread/thread/78975372cdfb7d1a

1: http://code.google.com/p/soc/wiki/PythonStyleGuide#Module_and_package_imports

12 голосов
/ 11 октября 2008

Я бы обычно использовал import X на уровне модуля. Если вам нужен только один объект из модуля, используйте from X import Y.

Используйте import X as Y только в том случае, если вы столкнулись с конфликтом имен.

Я использую импорт только на уровне функций для импорта необходимых мне вещей, когда модуль используется в качестве основного модуля, например:

def main():
  import sys
  if len(sys.argv) > 1:
     pass

НТН

9 голосов
/ 18 апреля 2013

Кто-то выше сказал, что

from X import A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P

эквивалентно

import X

import X разрешает прямые модификации A-P, а from X import ... создает копии A-P. Для from X import A..P вы не получите обновления переменных, если они изменены. Если вы изменяете их, вы изменяете только свою копию, но X знает о ваших изменениях.

Если A-P являются функциями, вы не узнаете разницу.

5 голосов
/ 11 октября 2008

Другие охватили большую часть темы здесь, но я просто хотел добавить один случай, где я буду использовать import X as Y (временно), когда я пробую новую версию класса или модуля.

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

import xyz_new as xyz

Затем, как только мы пересекаем всю кодовую базу, мы просто заменим модуль xyz на xyz_new и вернем весь импорт обратно на

import xyz
3 голосов
/ 11 октября 2008

НЕ делайте этого:

from X import *

, если вы не уверены, что будете использовать все в этом модуле. И даже тогда вам, вероятно, следует пересмотреть вопрос об использовании другого подхода.

Кроме этого, это просто вопрос стиля.

from X import Y

хорошо и экономит много печатать. Я склонен использовать это, когда я использую что-то в этом довольно часто. Но если вы много импортируете из этого модуля, вы можете получить инструкцию import, которая выглядит так:

from X import A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P

Вы поняли идею. Вот тогда импорт как

import X

стал полезным. Либо так, либо я не очень часто использую что-либо в X.

2 голосов
/ 11 октября 2008

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

Например, я бы сделал ..

from BeautifulSoup import BeautifulStoneSoup as BSS

.. так что я могу сделать soup = BSS(html) вместо BeautifulSoup.BeautifulStoneSoup(html)

Или ..

from xmpp import XmppClientBase

.. вместо импорта всего xmpp, когда я использую только XmppClientBase

Использование import x as y удобно, если вы хотите импортировать либо очень длинные имена методов, либо для предотвращения путаницы в существующем импорте / переменной / классе / методе (чего вам следует избегать полностью, но это не всегда возможно)

Скажем, я хочу запустить функцию main () из другого скрипта, но у меня уже есть функция main () ..

from my_other_module import main as other_module_main

.. не заменит мою main функцию на main

my_other_module

О, одно - не делайте from x import * - это делает ваш код очень трудным для понимания, так как вы не можете легко увидеть, откуда появился метод (from x import *; from y import *; my_func() - где определяется my_func?)

Во всех случаях вы могли бы просто сделать import modulename, а затем modulename.subthing1.subthing2.method("test") ...

Материал from x import y as z предназначен исключительно для удобства - используйте его всякий раз, когда ваш код будет легче читать или писать!

1 голос
/ 15 октября 2008

Когда у вас есть хорошо написанная библиотека, что иногда встречается в python, вы должны просто импортировать ее и использовать как есть. Хорошо написанная библиотека имеет тенденцию брать жизнь и язык самостоятельно, в результате чего получается приятный для чтения код, где вы редко ссылаетесь на библиотеку. Когда библиотека написана хорошо, вам не нужно слишком часто переименовывать или что-либо еще.

import gat

node = gat.Node()
child = node.children()

Иногда невозможно написать это таким образом, или тогда вы захотите убрать вещи из библиотеки, которую вы импортировали.

from gat import Node, SubNode

node = Node()
child = SubNode(node)

Иногда вы делаете это для многих вещей, если ваша строка импорта переполняет 80 столбцов, это хорошая идея сделать это:

from gat import (
    Node, SubNode, TopNode, SuperNode, CoolNode,
    PowerNode, UpNode
)

Лучшая стратегия - сохранить все эти операции импорта в верхней части файла. Предпочтительно упорядочить в алфавитном порядке, сначала импортировать -statements, а затем из import -statements.

Теперь я скажу вам, почему это лучшее соглашение.

В Python вполне мог бы быть автоматический импорт, который бы искал значение из основного импорта, если его нельзя найти в глобальном пространстве имен. Но это не очень хорошая идея. Я коротко объясню почему. Помимо того, что это сложнее в реализации, чем простой импорт, программисты не будут так много думать о зависимостях и выяснять, откуда вы импортировали вещи, следует делать не так, как просто просмотр импорта.

Необходимость выяснить зависимости - одна из причин, по которой люди ненавидят "из ... импорта *". Хотя существуют и плохие примеры, где вам нужно это сделать, например, opengl -wrappings.

Таким образом, определения импорта на самом деле ценны как определение зависимостей программы. Это способ, которым вы должны их использовать. Из них вы можете быстро проверить, откуда импортирована какая-то странная функция.

0 голосов
/ 10 февраля 2010

Я с Джейсоном по факту не пользуюсь

from X import *

Но в моем случае (я не опытный программист, поэтому мой код не слишком хорошо соответствует стилю кодирования) Я обычно делаю в своих программах файл со всеми константами, такими как версия программы, авторы, сообщения об ошибках и все этот материал, так что файл просто определения, а затем я делаю импорт

from const import *

Это экономит мне много времени. Но это единственный файл, который имеет этот импорт, и потому, что все внутри этого файла - просто объявления переменных.

Выполнение такого импорта в файле с классами и определениями может быть полезным, но когда вам приходится читать этот код, вы тратите много времени на поиск функций и классов.

0 голосов
/ 11 октября 2008

import X as Y полезно, если у вас разные реализации одного и того же модуля / класса.

С некоторыми вложенными try..import..except ImportError..import s вы можете скрыть реализацию от своего кода. См. пример импорта lxml etree :

try:
  from lxml import etree
  print("running with lxml.etree")
except ImportError:
  try:
    # Python 2.5
    import xml.etree.cElementTree as etree
    print("running with cElementTree on Python 2.5+")
  except ImportError:
    try:
      # Python 2.5
      import xml.etree.ElementTree as etree
      print("running with ElementTree on Python 2.5+")
    except ImportError:
      try:
        # normal cElementTree install
        import cElementTree as etree
        print("running with cElementTree")
      except ImportError:
        try:
          # normal ElementTree install
          import elementtree.ElementTree as etree
          print("running with ElementTree")
        except ImportError:
          print("Failed to import ElementTree from any known place")
...