Заполнение пространства имен внутри модуля перед его загрузкой - PullRequest
3 голосов
/ 24 декабря 2010

Я разработал механизм конфигурации в Python, где определенные объекты могут работать особым образом для определения проблем в нашем домене.

Пользователь указывает проблему, используя эти объекты в «файле конфигурации».Например:

# run configuration
CASES = [
 ('Case 1', Item('item1') + Item('item2') + Item('item3')),
 ('Case 2', Item('item1') + Item('item4')),
]

DATA = {
 'Case 1' = {'Piece 1': 'path 1'},
 'Case 2' = {'Piece 1': 'path 2'},
}

Объекты Item, конечно, определены в определенном модуле.Чтобы использовать их, вы должны выполнить оператор import: from models import Item (конечно, мой фактический импорт более сложен, а не один).

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

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

Любой совет?

Редактировать:

Рабочий процесс моей системы несколько похож на Django, в котором пользователь определяет «Настройки» в файле Python и запускает скрипт, который импортируетэтот файл настроек и делает с ним дела.Именно здесь я хотел бы, чтобы эта функциональность говорила Python: «учитывая это пространство имен (где Item означает что-то конкретное), пользователь предоставит сценарий - запустите его и передайте мне результат, чтобы я мог порождать различные прогоны».

Ответы [ 2 ]

1 голос
/ 24 декабря 2010

Из справки eval:

>>> help(eval)
Help on built-in function eval in module __builtin__:

eval(...)
    eval(source[, globals[, locals]]) -> value

    Evaluate the source in the context of globals and locals.
    The source may be a string representing a Python expression
    or a code object as returned by compile().
    The globals must be a dictionary and locals can be any mapping,
    defaulting to the current globals and locals.
    If only globals is given, locals defaults to it.

То есть вы можете передать произвольный словарь для использования в качестве пространства имен для вызова eval.

with open(source) as f:
    eval(f.read, globals(), {'Item': Item}) 

Почему вы решили, что пользователь должен написать свой файл конфигурации на чистом Python? Есть много простых написанных человеком языков, которые вы могли бы использовать вместо этого. Посмотрите, например, ConfigParser, который считывает основные файлы конфигурации, используемые Windows.

[cases]
case 1: item1 + item2 + item3
case 2: item1 + item4

[data]
case 1: piece1 - path1
case 2: piece1 - path2
0 голосов
/ 24 декабря 2010

1) первое, что я имею в виду, это предложить пользователю генерацию вашего конфигурационного файла;как так ?

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

$ python application_run.py --generate_settings 

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

import sys
from models import Item

# Complete the information here please !!!
CASES = []
DATA = {}

2) второй способ заключается в использовании execfile () , вы можете для этого создать скрипт, который будет читать settings.py:

root_settings.py

# All import defined Here.
from Model import Item
...

execfile('settings.py')

А теперь, чтобы прочитать информацию о файле настроек, просто импортируйте root_settings, так как все переменные, определенные в settings.py, теперь находятся в пространстве имен root_settings.py.

...