2008-09-26 5 views
106

__debug__ 변수는 모든 모듈에 영향을주기 때문에 편리합니다. 같은 방식으로 작동하는 다른 변수를 만들고 싶다면 어떻게해야합니까?Python : 모듈 간 변수를 만드는 방법은 무엇입니까?

변수 (원래대로하고 'foo'라고 부름)는 진정으로 전역적일 필요는 없습니다. 한 모듈에서 foo를 변경하면 다른 모듈에서도 업데이트됩니다. 다른 모듈을 가져 오기 전에 foo를 설정할 수 있다면 똑같은 값을 볼 수 있습니다.

답변

94

나는이 솔루션을 어떤 식 으로든, 모양 또는 형태로 보증하지 않습니다. 그러나 __builtin__ 모듈에 변수를 추가하면 기본적으로 __builtin__을 포함하는 다른 모듈의 전역 변수처럼 액세스 할 수 있습니다.

a.py는

print foo 

b.py의 결과가 "1"이 출력된다는 점이다

import __builtin__ 
__builtin__.foo = 1 
import a 

포함 포함한다.

편집 : __builtin__ 모듈은 로컬 기호 __builtins__로 사용할 수 있습니다 - 즉, 이러한 응답의 둘 사이의 차이에 대한 이유입니다. 또한 __builtin__은 python3에서 builtins으로 이름이 변경되었습니다.

+2

어떤 이유로 든이 상황을 좋아하지 않습니까? –

+26

한 가지 사실은 사람들이 코드를 읽을 때 사람들의 기대를 깨뜨리는 것입니다. "이 'foo'심볼이 여기에 사용되는 이유는 무엇입니까? 왜 그것이 정의되어 있는지 알 수없는 이유는 무엇입니까?" –

+8

파이썬의 차기 버전이 실제 내장 된 것으로 선택한 이름을 사용하기 시작하면 혼란을 겪을 수도 있습니다. – intuited

2

이름 공간이 __builtin__ 인 것처럼 들립니다. 이 작업을 수행하려면 :

import __builtin__ 
__builtin__.foo = 'some-value' 

는 ("s"가 통지) 직접 __builtins__를 사용하지 마십시오 - 분명히이 사전 또는 모듈이 될 수 있습니다. 이 문제를 지적한 ΤΖΩΤΖΙΟΥ 덕분에 더 많은 것이 here이라고 할 수 있습니다.

이제 foo을 어디에서나 사용할 수 있습니다.

일반적으로 권장하지는 않지만 프로그래머는이를 사용하는 것이 좋습니다.

위와 같이 지정해야합니다. foo = 'some-other-value'을 설정하면 현재 네임 스페이스에서만 설정됩니다.

+1

저는 comp.lang.python에서 직접 __builtins__를 사용하는 것을 피해야한다고 기억합니다. 대신 Curt Hagenlocher가 제안한대로 __builtin__을 가져 와서 사용하십시오. – tzot

20

모듈을 정의하고 ("globalbaz"라고 함) 모듈 내부에 변수가 정의되어 있어야합니다. 이 "pseudoglobal"을 사용하는 모든 모듈은 "globalbaz"모듈을 가져 와서 "globalbaz.var_name"을 사용하여 참조해야합니다.

이 작업은 변경 위치에 관계없이 가져 오기 전 또는 후에 변수를 변경할 수 있습니다 . 가져온 모듈은 최신 값을 사용합니다. 당신이 글로벌 크로스 모듈 변수가 필요한 경우

var_name = "my_useful_string" 
131

것은 어쩌면 그냥 간단한 전역 모듈 수준 변수가 충분 : 대한 명확한

이 globalbaz.py 그냥 다음과 같습니다 (I 장난감 예제에서이 테스트) .

a.py :

var = 1 

나.평 :

import a 
print a.var 
import c 
print a.var 

c.py :

import a 
a.var = 2 

테스트 :

$ python b.py 
# -> 1 2 

실제적인 예 : Django's global_settings.py (장고 설정이 객체django.conf.settings을 가져 와서 사용하는 애플 리케이션을하지만).

+2

네임 스페이스 충돌을 피할 수 있기 때문에 더 좋음 – bgw

+0

가져 오는 모듈 (이 경우'a.py')에'main()'이 있으면 어떨까요? 그게 그렇게 중요한 건가? – sedeh

+4

@sedeh : no. 또한 a.py가 스크립트로 실행되는 경우 가져 오기에서 예기치 않은 코드가 실행되지 않도록하기 위해'if __name __ == "__ main __"'가드를 사용하십시오. – jfs

7

전역 변수는 일반적으로 나쁜 생각,하지만 당신은 __builtins__에 할당하여이 작업을 수행 할 수 있습니다

__builtins__.foo = 'something' 
print foo 

은 또한, 모듈

자체는 어떤 모듈에서 액세스 할 수있는 변수입니다. 당신이 my_globals.py라는 모듈을 정의한다면 :

import my_globals 
print my_globals.foo 

모듈을 사용하기보다는 __builtins__ 수정 일반적으로 이런 종류의 전역을 할 수있는 청소기 방법입니다

# my_globals.py 
foo = 'something' 

그런 다음 당신은뿐만 아니라 어디서든 것을 사용할 수 있습니다 .

+2

'__builtins__'는 CPython의 특성입니다. 정말 사용하면 안됩니다 - Python3의'__builtin__' (또는'builtins')을 [받아 들인 대답] (http://stackoverflow.com/a/142566/321973)으로 사용하는 것이 좋습니다.)는 테스트를 위해 –

9

당신은 onother 한 모듈의 전역을 전달할 수 있습니다

를 모듈 A에서 :

import module_b 
my_var=2 
module_b.do_something_with_my_globals(globals()) 
print my_var 

를 모듈 B에서 :

def do_something_with_my_globals(glob): # glob is simply a dict. 
    glob["my_var"]=3 
+2

을 보여줍니다! –

5

이미 모듈 수준이 작업을 수행 할 수 있습니다 변수. 모듈은 가져온 모듈과 상관없이 동일합니다. 따라서 변수를 넣고 변수에 액세스하거나 다른 모듈에서 할당하는 것이 타당한 모듈에서 변수를 모듈 수준의 변수로 만들 수 있습니다. 변수의 값을 설정하는 함수를 호출하거나 특정 객체의 속성으로 사용하는 것이 좋습니다. 그런 식으로 변수가 변경되었을 때 코드를 실행할 필요가 생기면 모듈의 외부 인터페이스를 깨지 않고 그렇게 할 수 있습니다.

일반적으로 전역을 사용하는 것이 좋지 않지만, 이것이 가장 깨끗한 방법이라고 생각합니다.

1

필자는 실제로 실종 된 몇 가지 내장 기본 함수에 이것을 사용합니다. 한 가지 예는 filter, map, reduce와 같은 사용법을 갖는 find 함수입니다. 이 번

def builtin_find(f, x, d=None): 
    for i in x: 
     if f(i): 
      return i 
    return d 

import __builtin__ 
__builtin__.find = builtin_find 

하지만, 분명히, 그것은 년에 지어진로 발견()를 사용할 수있는 모든 모듈 (예를 들어, 귀하의 진입 점 근처에 가져 와서) 실행

find(lambda i: i < 0, [1, 3, 0, -5, -10]) # Yields -5, the first negative. 

주. : 물론 필터와 다른 줄을 사용하여 길이가 0 인 것을 테스트하거나 이상한 줄의 줄을 줄일 수는 있지만, 항상 이상하다고 느꼈습니다.

20

필자는 이해할 수있는 상황이 많으며 여러 개의 (단단히 결합 된) 모듈에 알려진 일부 전역을 포함하도록 프로그래밍을 단순화한다고 생각합니다.이 정신에서 나는 그들을 참조 할 필요가있는 모듈에 의해 수입되는 전역의 모듈을 갖는 아이디어에 대해 좀 더 자세히 설명하고자한다.

이러한 모듈이 하나만있는 경우 이름을 "g"로 지정합니다. 여기서는 글로벌 변수로 처리하려는 모든 변수에 기본값을 할당합니다. 이들 중 하나를 사용하는 각 모듈에서 "g import var"를 사용하지 않습니다.이 경우 가져 오기시에만 g로 초기화되는 로컬 변수가 생성됩니다. 나는 대부분의 참조를 g.var 형식으로 만들고 "g". 나는 다른 모듈에서 잠재적으로 액세스 할 수있는 변수를 다루고 있다는 끊임없는 알림으로 작용합니다.

전역 변수의 값이 모듈의 일부 함수에서 자주 사용되는 경우이 함수는 로컬 복사를 할 수 있습니다. var = g.var. 그러나, var 에의 할당은 로컬이며, 글로벌 g.var는 할당에서 명시 적으로 g.var를 참조하지 않고는 갱신 될 수 없다는 것을 인식하는 것이 중요합니다.

또한 이러한 여러 전역 모듈을 모듈의 여러 하위 집합에서 공유하여 좀 더 긴밀하게 제어 할 수 있습니다. 전역 모듈에 짧은 이름을 사용하는 이유는 코드가 너무 많이 어지럽히는 것을 피하기 위해서입니다. 약간의 경험만으로도 1 ~ 2 자 정도의 니모닉이됩니다.

x가 g에 아직 정의되지 않은 경우 g.x와 같은 지정을 할 수 있으며 다른 모듈이 g.x에 액세스 할 수 있습니다. 그러나 통역사가 그것을 허용하더라도,이 접근법은 그렇게 투명하지 않으며, 나는 그것을 피한다. 과제의 변수 이름에 오타가 생긴 결과로 실수로 g에 새로운 변수가 생성 될 가능성이 있습니다. 때로는 dir (g)을 검사하면 그러한 사고로 인해 발생할 수있는 놀랄 이름을 발견하는 데 유용합니다.

+5

이 흥미로운 관찰은 나의 문제를 해결했다 : 'g import var에서 "사용하지 않는다. 이것은 수입시에만 g로 초기화되는 로컬 변수를 생성하기 때문이다.' "from..import"는 "가져 오기"와 동일하지만 이는 사실이 아니라고 가정하는 것이 합리적입니다. –

0

I이 사전을 사용하여 교차 - 수정 모듈 (또는 가변 ) 변수를 달성 할 수 :

# in myapp.__init__ 
Timeouts = {} # cross-modules global mutable variables for testing purpose 
Timeouts['WAIT_APP_UP_IN_SECONDS'] = 60 

# in myapp.mod1 
from myapp import Timeouts 

def wait_app_up(project_name, port): 
    # wait for app until Timeouts['WAIT_APP_UP_IN_SECONDS'] 
    # ... 

# in myapp.test.test_mod1 
from myapp import Timeouts 

def test_wait_app_up_fail(self): 
    timeout_bak = Timeouts['WAIT_APP_UP_IN_SECONDS'] 
    Timeouts['WAIT_APP_UP_IN_SECONDS'] = 3 
    with self.assertRaises(hlp.TimeoutException) as cm: 
     wait_app_up(PROJECT_NAME, PROJECT_PORT) 
    self.assertEqual("Timeout while waiting for App to start", str(cm.exception)) 
    Timeouts['WAIT_JENKINS_UP_TIMEOUT_IN_SECONDS'] = timeout_bak 

test_wait_app_up_fail 발사 실제 타임 아웃 지속 기간을 3 초이다.

2

변수를 찾을 수없는 경우가 있다는 답변을 게시하고 싶습니다.

주기적으로 가져 오기하면 모듈 동작이 중단 될 수 있습니다. 예를 들어

:

first.py

import second 
var = 1 

second.py

import first 
print(first.var) # will throw an error because the order of execution happens before var gets declared. 

이를

import first 

그것이 명백해야 예이다 main.py, 그러나 큰 코드베이스에서, 이것은 r 일 수있다. 헷갈리는 eally.

관련 문제