Python Импорт модулей в пакете - PullRequest
0 голосов
/ 01 октября 2019

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

Я просто проверяю, как все это работает, прежде чем делать это по-настоящему, поэтому извиняюсь, если это кажется немного ненадежным.
Я создал папку с именем pack_test и в ней у меня есть:
__init__.py
foo.py
bar.py


__init__.py содержит:

__all__ = ['foo', 'bar']
from . import *
import subprocess
from os import environ

В консоли я могу написать import pack_test as pt и это нормально, без ошибок.
pt. и две вкладки показывают мне, что я вижу там pt.bar, pt.environ, pt.foo и pt.subprocess.
Пока все хорошо.


Если я хочу сослаться на subprocess или environ в foo.py или bar.py, как мне там сделать?

Если в bar.py у меня естьфункция, которая просто делает return subprocess.call('ls'), ошибается, говоря: NameError: имя 'подпроцесс' не определено . Должно быть что-то, чего мне не хватает, что позволяет мне ссылаться на подпроцесс с уровня выше? Предположительно, как только я смогу получить синтаксис от этого, я смогу просто вызывать окружающую среду аналогичным образом?

Альтернативой, как я мог видеть, было бы иметь import subprocess в обоих foo.py и bar.pyно тогда мне кажется немного странным, чтобы он появлялся в нескольких файлах, когда я мог иметь его один раз на более высоком уровне, особенно если в этом примере у меня было больше файлов, чем просто 2.

Ответы [ 2 ]

1 голос
/ 01 октября 2019

TL; DR:

__init__.py:

import foo
import bar

__all__ = ["foo", "bar"]

foo.py:

import subprocess
from os import environ

# your code here

bar.py

import subprocess
from os import environ

# your code here

Должно быть, я чего-то упускаю, что позволяет мне ссылаться на подпроцесс с уровня выше?

Нет, это ожидаемое поведение.

import загружает модуль (если его еще нет), кэширует его в sys.modules (то же самое) и связывает импортированные имена в текущем пространстве имен. Каждый модуль Python имеет (или «есть») свое собственное пространство имен (нет реального «глобального» пространства имен). Итак, вы должны импортировать то, что вам нужно, в каждый модуль, т.е. если foo.py требуется subprocess, он должен явно импортировать его.

Сначала это может показаться утомительным, нов долгосрочной перспективе это действительно помогает в отношении поддержки и сопровождения - вам просто нужно прочитать импорт в верхней части вашего модуля (pep 08: всегда помещать все импорты в начало модуля), чтобы узнать, откуда происходит имя.

Кроме того, вы не должны использовать импорт звездочек (он же * подстановочный знак from xxx import *) где-либо еще, кроме как в вашей оболочке Python (и даже тогда ...) - это бомба замедленного действия. Не только потому, что вы не знаете, откуда происходит каждое имя, но и потому, что это верный способ связать уже импортированное имя. Представьте, что ваш модуль foo определяет функцию «func». Где-то у вас есть "из импорта foo *; из импорта бара *", затем в коде вызов функции. Теперь кто-то редактирует bar.py и добавляет (отдельную) функцию «func», и внезапно вы вызываете ошибку, потому что вы не вызываете ожидаемый «func». Теперь наслаждайтесь отладкой этого ... И примеры из реальной жизни, как правило, немного сложнее, чем это.

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

(здесь, сделали это и т. д.)

0 голосов
/ 01 октября 2019

Вы можете создать modules.py, содержащий

import subprocess
import os

Тогда в foo.py или любом из ваших файлов просто есть.

from modules import *

Ваши операторы импортатогда ваши файлы статичны и просто обновите modules.py, если вы хотите добавить дополнительный модуль, доступный для них всех.

...