2008-10-11 6 views
70

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

import X 
import X as Y 
from A import B 

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

На мой вопрос не ответил "Python packages - import by class, not file", хотя это, очевидно, связано.

+0

См. Http://stackoverflow.com/questions/187453/import-package-vs-import-packagespecifictype – 2008-10-11 10:33:53

+0

См. Http://stackoverflow.com/questions/186472/from-x-import-a-versus-import -x-xa – 2008-10-11 10:35:11

ответ

63

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

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

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

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

+4

«они просто делают код медленнее», это не так. Он был протестирован здесь: http://stackoverflow.com/a/4789963/617185 – kmonsoor 2015-06-08 07:17:25

12

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

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

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

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

HTH

0

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

С некоторыми вложенными try..import..except ImportError..import s вы можете скрыть реализацию от вашего кода. См 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") 
2

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

К примеру, я бы ..

from BeautifulSoup import BeautifulStoneSoup as BSS 

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

Или ..

from xmpp import XmppClientBase 

..instead от импорта цельные из XMPP, когда я использую только XmppClientBase

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

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

from my_other_module import main as other_module_main 

..wouldn't заменить мою main функцию с my_other_module в main

О, одна вещь - не делать 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 материал исключительно для удобства - использовать его всякий раз, когда это будет сделать легче читать или писать код!

+2

IMHO, здесь есть некоторые заблуждения ... 1) * «импортирование всего xmpp, когда я использую только ...» *: это ложно подразумевает, что этот подход «легче», но Python будет загружать и запускать весь модуль в любом случае независимо от того, сколько объектов вы импортировали. Что касается «загрязнения пространства имен», то оба добавят * одиночную * запись в локальное пространство имен: `xmpp` или` XmppClientBase`. Таким образом, это обоснование недействительно – MestreLion 2012-04-13 19:46:48

+2

2) * «поскольку вы не можете легко увидеть, откуда пришел метод« *: True для * import, но * также * true для вашего подхода использования `as`, чтобы просто сократить имя модуля/объекта , Откуда берется «BSS()»? Использование `from` также немного (см.):` From mymod import MyClass`. Теперь на 300 строк вы увидите «класс MyOtherClass (MyClass):` ... теперь, откуда появился MyClass? Читатель вынужден всегда вернуться в заголовок, чтобы посмотреть, где был импортирован какой-либо объект из – MestreLion 2012-04-13 19:57:42

5

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

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

import xyz_new as xyz 

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

import xyz 
+0

Вы избили меня до него. – 2008-10-11 14:30:29

3

НЕ делать это:

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 очень часто.

+0

'от X import *' имеет свои применения - например. с пипарированием. – 2008-10-12 21:44:51

34

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

[...] Например, это часть руководств по стилю 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

1

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

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

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

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

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

0

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

from X import * 

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

from const import * 

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

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

8

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

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

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

import X 

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

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

Смежные вопросы