2009-02-03 3 views
2

Я работаю над своим первым значительным проектом Python, и у меня возникают проблемы с проблемами области и выполнением кода во вложенных файлах. Ранее мой опыт работы с PHP.Python включает в себя проблему с объемом модуля

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

В любом случае, я ищу общий совет по наилучшему структурированию кода для достижения того, что я хочу.

Спасибо!

ответ

0

Насколько я знаю глобальные переменные/функции/классы программы и т. Д. не существует в Python, все «ограничено» в некотором модуле (пространство имен). Поэтому, если вы хотите, чтобы некоторые функции или классы использовались во многих частях вашего кода, одно из решений создает некоторые модули, такие как: «globFunCl» (определение/импорт из других источников, все, что вы хотите быть «глобальными») и «config» (содержащие конфигурацию переменные) и импортировать их везде, где они вам нужны. Если вам не нравится идея использования вложенных пространств имен вы можете использовать:

from globFunCl import * 

Таким образом, вы будете «скрыть» Пространство имен (делая имена похожи на «глобал»).

Я не уверен, что вы имеете в виду, не желая «положить всю рутину в начале каждого (включенного) файла, чтобы включить все остальное», боюсь, вы не сможете убежать из этого. Проверьте, Python Packages, хотя они должны облегчить вам.

6

В python принято распространять множество модулей, которые реализуют различные функции, а затем имеют один единственный модуль, который является точкой доступа ко всем функциям. Это в основном facade pattern.

Пример: говорят, что вы пишете пакет foo, который включает в себя bar, baz и moo модули.

~/project/foo 
~/project/foo/__init__.py 
~/project/foo/bar.py 
~/project/foo/baz.py 
~/project/foo/moo.py 
~/project/foo/config.py 

Что бы вы, как правило, это написать __init__.py так:

from foo.bar import func1, func2 
from foo.baz import func3, constant1 
from foo.moo import func1 as moofunc1 
from foo.config import * 

Теперь, когда вы хотите использовать функции, которые вы просто делаете

import foo 
foo.func1() 
print foo.constant1 
# assuming config defines a config1 variable 
print foo.config1 

Если вы хотите , вы можете упорядочить свой код, чтобы вам нужно было написать только

import foo 

В верхней части каждого модуля, а затем получить доступ ко всему через foo (который вы, вероятно, должны назвать «глобальными» или что-то в этом роде).Если вам не нравится пространство имен, можно даже сделать

from foo import * 

и есть все, как глобальные, но это на самом деле не рекомендуется. Помните: пространства имен - одна хорошая идея!

1

Это двухступенчатый процесс:

  1. В вашем модуле globals.py импортировать элементы из любого места.
  2. Во всех других ваших модулей, делать «от Глобалы импорта *»

Это приносит все эти имена в пространство имен текущего модуля.

Теперь, сообщив вам, как это сделать, позвольте предложить вам не. Прежде всего, вы загружаете локальное пространство имен кучей «магически определенных» объектов. Это нарушает предписание 2 из Zen of Python: «Явное лучше, чем неявное». Вместо «from foo import *» попробуйте использовать «import foo», а затем «foo.some_value». Если вы хотите использовать короткие имена, используйте «from foo import mumble, snort». Любой из этих методов непосредственно раскрывает фактическое использование модуля foo.py. Использование метода globals.py просто слишком магия. Основное исключение - это __init__.py, где вы скрываете некоторые внутренние аспекты пакета.

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

Я знаю, что PHP имеет это понятие «все одно, большое, счастливое пространство имен», но это действительно просто артефакт плохого дизайна языка.

0

Это зависит от того, как вы хотите упаковать вещи. Вы можете думать в терминах файлов или модулей. Последний «более pythonic» и позволяет вам точно определить, какие элементы (и они могут быть любыми с именем: классами, функциями, переменными и т. Д.), Которые вы хотите сделать видимыми.

Основным правилом является то, что для любого импортируемого файла или модуля можно получить доступ к чему-либо непосредственно в своем пространстве имен. Так что, если myfile.py содержит определение def myfun(...): и class myclass(...), а также myvar = ... то вы можете получить доступ к ним из другого файла,

import myfile 
y = myfile.myfun(...) 
x = myfile.myvar 

или

from myfile import myfun, myvar, myclass 

Кардинальны, все на высшем уровне MYFILE доступны, включая импорт. Так что если myfile содержит from foo import bar, то также можно найти myfile.bar.

0

Другие говорили о правильном способе сделать это с Python.

Позвольте мне добавить, однако, что если пользователи меняют исходный файл, чтобы настроить ваше приложение, хотя оно и распространено в мире PHP, не очень Pythonic. Рассмотрите возможность использования стандартного библиотечного модуля ConfigParser или стороннего модуля ConfigObj (который поддерживает сложные типы данных, такие как вложенные диктофоны, списки и т. Д.), Чтобы вместо этого проанализировать файл конфигурации.

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