2015-08-19 8 views
3

В моих проблемах у меня есть код питона, который будучи запущен пользователем, как:Как использовать глобальную переменную в python?

# file main.py 
import sys 
import mymodule 
config = sys.argv[1] 

который импортирует другой модуль, содержащие функции, классы и т.д., как

# module.py 
def check_config(): 
    # do something with the content of 'config' 
class Module(object): 
    # does something with the content of 'config' 

Как я могу получить доступ к значение 'config' от module.py? Должен ли я использовать здесь глобальную переменную? Или существует более сложный, питонический способ решения этой проблемы?

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

Далее замечание: main.py импортирует другие модули, а не наоборот ...

ответ

2

Вместо того чтобы пытаться пресекать global, для этого необходимо передать config в качестве параметра.

файл main.py

import sys 
import mymodule 
config = sys.argv[1] 

checked = mymodule.check_config(config) 
mod = mymodule.Module(config) 

module.py

def check_config(config): 
    # do something with the content of 'config' 
class Module(object): 
    # does something with the content of 'config' 
    def __init__(self, config): 
     # initialise with config 

Всегда избегать использования global, когда вы можете. Если вам нужно изменить config, просто имейте функцию модуля вернуть его.

config = change_config(config) 

module.py

def change_config(config): 
    ... 
    return config 

Однако альтернативный метод для определения значения в пределах module.py, который будет хранить эту информацию, которая не держит ничего по умолчанию. Затем, как только file main.py импортирует module.py, и данные конфигурации готовы, вы можете присвоить данные конфигурационному имени module.py. Как это:

файл main.py

import sys 
import mymodule 
config = sys.argv[1] 

mymodule.config = config 

mymodule.test_config() 
mymodule.check_config() 
mymodule.Module() 

module.py

config = None 

def test_config(): 
    print config 
    # this will refer to the value supplied from file main.py 

Однако обратите внимание, что значения в модуле и основной файл не будет присоединен. Если вы переназначаете конфигурацию в file main.py по какой-либо причине, вам нужно снова передать это значение модулю. Однако, если вы передадите изменяемое значение, например, dict или list, вы можете изменить его в file main.py, и значения будут доступны.

+0

Автобус, как я уже упоминал, может иметь десятки классов и сотни функций. Ваш подход не кажется очень «питоническим». – Alex

+0

@Alex Передача параметра - это чистый способ получить функцию для получения этого параметра. Использование 'global' будет неясным из-за того, что он менее явный. Быть явным * является * Pythonic. – SuperBiasedMan

+0

Что вы думаете о описанном здесь подходе: http://effbot.org/pyfaq/how-do-i-share-global-variables-across-modules.htm – Alex

1

Глобальная переменная почти никогда не является ответом. Просто разрешите функции и классы в вашей «библиотеке» (module.py или mymodule.py, вы, кажется, используете оба), чтобы принимать аргументы. So:

mymodule.PY

def check_config(configuration): 
    pass 

class Module(object): 
    def __init__(self, configuration): 
     self.config = configuration 

class ConfigError(Exception): 
    pass 

Затем, когда вы хотите использовать их в "приложение" Код:

main.py

import sys 
import mymodule 

config = sys.argv[1] 

if mymodule.check_config(config): 
    myobject = mymodule.Module(config) 
else: 
    raise mymodule.ConfigError('Unrecognized configuration format.') 
+0

Тот же комментарий, что и ниже: Это может работать, но тогда 'Module' вызывает разные функции и классы, которые в свою очередь вызывают другие функции и классы. И для каждого из них я должен определить тот же аргумент. Выглядит неплохо для меня ... – Alex

+0

Ум, повторное использование кода - это что-то вроде этого. На самом деле не следовало вашей логике. Другим способом было бы поместить весь ваш код конфигурации в файл config.py, скажем, а затем «импортировать конфигурацию» во все файлы вашей библиотеки, но вы упомянули, что не хотите «импортировать» в свои библиотеки. Вы слишком ограничиваете свой приемлемый набор решений. –

0

Не могли бы вы описать, что вы приложение должно делать? Потому что теперь неясно, зачем вам это нужно. Может быть, переменная окружения может вам помочь?

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

config.py

import os 
    if os.environ['sys'] == 'load_1': 
     import load_1 as load 
     i = 12 
    else: 
     import load_2 as load 
     i = 13 

main.py

import config 

    config.load("some_data") 
    print config.i 
+0

Однако переменная, используемая в модулях и функциях, может различаться между разными экземплярами одного и того же кода на Python. Я начинаю, например. 5 экземпляров для параллельной работы, но с другой конфигурацией или любым другим. Поэтому ваш подход не решит мою проблему. – Alex

+0

Это озадачивает! Тем более разумно принять понятие о явной передаче в свои объекты конфигурации каждый раз, принимая мое решение или @ SuperBiasedMan's. –

+0

@Alex, вам просто нужно запустить его с другой конфигурацией. Вы можете передать конфигурационную конфигурацию, как переменную среды, в модуль 'config', проанализировать эту конфигурацию и использовать ее в каждом модуле, который вы хотите. – Jimilian

2

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

# file main.py 
import sys 
import mymodule 
mymodule.config = sys.argv[1] 


# module.py 
# The exact value doesn't matter, as long as we create the name. 
# None is good as it conveys the lack of a value; it's part of your 
# module's contract, presumably, that a proper value must be assigned 
# before you can use the rest of the module. 
config = None 
def check_config(): 
    # do something with the content of 'config' 
class Module(object): 
    # does something with the content of 'config' 
+0

Я предполагаю, что это аналогичный подход, приведенный здесь: http://effbot.org/pyfaq/how-do-i-share-global-variables-across-modules.htm? – Alex

+0

Да, это не жесткий образ воссоздать. По сути, модуль рассматривается как класс, который создается только один раз. Глобалы модуля являются переменными экземпляра, и любые функции модуля являются методами. – chepner

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