Каковы правила для импорта в Python?


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

import X
import X as Y
from A import B

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

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

10 70

10 ответов:

в коде продукции в нашей компании, мы пробуем следовать следующими правилами.

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

"""
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

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

позвольте мне просто вставить часть разговора в список рассылки django-dev, начатый Guido van Rossum:

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

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

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

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

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

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

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

HTH

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

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 функции, вы не будете знать разницу.

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

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

import xyz_new as xyz

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

import xyz

не делай этого:

from X import *

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

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

from X import Y

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

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

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

import X

стать полезным. Или если я не очень часто в X.

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

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

from BeautifulSoup import BeautifulStoneSoup as BSS

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

или..

from xmpp import XmppClientBase

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

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

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

from my_other_module import main as other_module_main

..не заменил бы мой main функция с my_other_module's main

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

во всех случаях может просто делать import modulename а потом сделать modulename.subthing1.subthing2.method("test")...

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

когда у вас есть хорошо написанная библиотека, что иногда бывает в 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
)

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

Теперь я скажу вам, почему это лучший съезд.

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

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

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

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

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

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")

Я с Джейсоном в том, что не использую

from X import *

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

from const import *

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

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