2013-02-13 5 views
0

для того, чтобы свести к минимуму жёстко прописанные значения на протяжении всей моей программы, я определил набор констант, как показано в следующем Constants.py:перекрывая набор пространствами имен констант

FOO = 42 
HOSTNAME=socket.gethostname() 
BAR = 777 

все модули, которые хотят использовать эти константы, просто сделать import Constants и сразу же использовать Constants.FOO.

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

FOO = 42 
HOSTNAME=socket.gethostname() 
if HOSTNAME == 'pudel': 
    BAR = 999 
elif HOSTNAME == 'knork' 
    BAR = 888 
else: 
    BAR = 777 

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

, если я был в этом оболочка-сценариев я хотел бы использовать что-то вроде этого Constants.sh:

FOO = 42 
HOSTNAME=$(hostname) 
BAR = 777 

# load host-specific constants 
if [ -e Constants_${HOSTNAME}.sh ]; then 
    . Constants_${HOSTNAME}.sh 
fi 

и дополнительный Constants_pudel.sh, который выглядит как:

BAR = 999 

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

так как я не пишу скрипт-скрипт, а программу-питон, мне было интересно, как добиться того же результата.

без толку я пытался что-то вроде:

FOO = 42 
HOSTNAME=socket.gethostname() 
BAR = 777 
try: 
    __import__('Constants_'+HOSTNAME) 
except ImportError: 
    pass 

и Constants_poodle.py будет выглядеть так:

import Constants 
Constants.BAR = 999 

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

не работает вообще, используя __import__() кажется исключительно уродливым, поэтому я думаю, что есть правильный способ переопределить экспортированные константы для конкретных настроек?

+0

* Эти константы могут зависеть от фактического хоста, на котором работает программа *. Тогда они не являются константами ... – gerrit

+0

ну, я считаю их постоянными в данном контексте. но не стесняйтесь редактировать квесто с лучшей формулировкой для тех * констант * –

ответ

1

У вашего решения есть несколько проблем. Во-первых, импорт не добавляет импортированный модуль в текущее пространство имен. Не уверен, что питон 3.x, но на Python 2.x Вы могли бы сделать что-то вроде:

FOO = 42 
BAR = 777 
HOSTNAME=socket.gethostname() 
try: 
    _imp = __import__('Constants_'+HOSTNAME) 
    _locals = locals() 
    for _name in dir(_imp): 
     if not _name.startswith('_'): 
      _locals[_name] = getattr(_imp, _name) 
    del _imp, _locals, _name 
except ImportError: 
    pass 

Но следующая проблема состоит в том, что все constants_xxx.py файлы должны быть в пути питона.

Альтернативное решение, которое, я думаю, будет работать лучше для вас, - это установить конфигурацию в файл .ini в каталоге пользователя и использовать ConfigParser (или yaml или xml в зависимости от ваших вкусов).

+0

Я думаю, что это то, что я искал ... дополнительные очки для решения .ini –

1

Вы могли бы сделать что-то подобное с нижеследующим, который получен из рецепта ActiveState Constants in Python:

import os as _os 
import socket as _socket 

class _constants(object): 
    def __init__(self): 
     self.FOO = 42 
     self.HOSTNAME = _socket.gethostname() 
     self.BAR = 777 

     # load host-specific constants 
     hostconst = 'Constants_{}'.format(self.HOSTNAME) 
     if _os.path.exists(hostconst): 
      localdict = {} 
      execdict = self.__dict__.copy() 
      execdict['__builtins__'] = None 
      execfile(hostconst, execdict, localdict) 
      self.__dict__.update(localdict) # add/override attributes defined 

    def __setattr__(self, name, value): 
     self.__dict__[name] = value 

# replace module entry in sys.modules[__name__] with instance of _constants 
# (and create additional reference to module so it's not deleted -- 
# see Stack Overflow question: http://bit.ly/ff94g6) 
import sys 
_ref, sys.modules[__name__] = sys.modules[__name__], _constants() 

if __name__ == '__main__': 
    import constants 

    print constants.FOO 
    print constants.HOSTNAME 
    print constants.BAR 

Так, например, если _socket.gethostname() вернулся «Пудель», и Constants_pudel файл существовал, содержащий следующие строки:

BAR = 999 
FOO += 1 

Тогда выход из print заявлений будет:

43 
pudel 
999 
Смежные вопросы