가져온 모듈의 전역 변수 가시성 엔터티로 지정). module1

Python 스크립트에서 모듈을 가져 오는 벽에 부딪 혔습니다. 오류를 설명하기 위해 최선을 다하고 오류가 발생하는 이유와 문제를 해결하기 위해이 특정 접근 방식을 사용하는 이유 (잠시 후 설명하겠습니다) :

이 보조 모듈을 가져올 네임 스페이스에 정의 된 엔터티를 참조하는 일부 유틸리티 함수 / 클래스를 정의한 모듈이 있다고 가정 해 보겠습니다 ( “a”를 이러한 엔터티로 지정).

module1 :

def f():
    print a

그리고 “a”가 정의 된 메인 프로그램이 있는데,이 프로그램으로 유틸리티를 가져 오려고합니다.

import module1
a=3
module1.f()

프로그램을 실행하면 다음 오류가 발생합니다.

Traceback (most recent call last):
  File "Z:\Python\main.py", line 10, in <module>
    module1.f()
  File "Z:\Python\module1.py", line 3, in f
    print a
NameError: global name 'a' is not defined

비슷한 질문이 과거 (이틀 전 d’ uh)에 제기되었으며 몇 가지 해결책이 제안되었지만 이것이 제 요구 사항에 맞지 않는다고 생각합니다. 내 특정 컨텍스트는 다음과 같습니다.

MySQL 데이터베이스 서버에 연결하고 GUI로 데이터를 표시 / 수정하는 Python 프로그램을 만들려고합니다. 청결을 위해 별도의 파일에 보조 / 유틸리티 MySQL 관련 함수를 정의했습니다. 그러나 그들은 모두 내가 원래 유틸리티 모듈 내부 에 정의 하고 MySQLdb 모듈 의 커서 객체 인 공통 변수를 가지고 있습니다. 나중에 db 서버와 통신하는 데 사용되는 커서 개체가 주 모듈에 정의되어 주 모듈과 여기로 가져온 모든 것이 해당 개체에 액세스 할 수 있어야 한다는 것을 나중에 깨달았습니다 .

최종 결과는 다음과 같습니다.

utility_module.py :

def utility_1(args):
    code which references a variable named "cur"
def utility_n(args):
    etcetera

그리고 내 주요 모듈 :

program.py :

import MySQLdb, Tkinter
db=MySQLdb.connect(#blahblah) ; cur=db.cursor()  #cur is defined!
from utilities_module import *

그리고 유틸리티 함수를 호출하려고하면 앞서 언급 한 “글로벌 이름이 정의되지 않음”오류가 발생합니다.

특별한 제안은 다음과 같이 유틸리티 파일에 “from program import cur”문을 포함하는 것이 었습니다.

utility_module.py :

from program import cur
#rest of function definitions

program.py :

import Tkinter, MySQLdb
db=MySQLdb.connect(#blahblah) ; cur=db.cursor()  #cur is defined!
from utilities_module import *

그러나 그것은 주기적 수입이나 그와 비슷한 것이고, 결론적으로도 충돌합니다. 그래서 제 질문은 :

도대체 어떻게 메인 모듈에 정의 된 “cur”객체를 가져 오는 보조 기능에 보이게 할 수 있습니까?

시간을 내 주셔서 감사합니다. 솔루션이 다른 곳에 게시 된 경우 진심으로 사과드립니다. 나는 스스로 답을 찾을 수 없으며 책에 더 이상 속임수가 없습니다.



답변

Python의 전역은 모든 모듈이 아닌 모듈 에 전역입니다. (예를 들어 C에서 전역은 명시 적으로 만들지 않는 한 모든 구현 파일에서 동일하기 때문에 많은 사람들이 이것을 혼동합니다 static.)

실제 사용 사례에 따라이를 해결하는 방법에는 여러 가지가 있습니다.


이 길을 가기 전에 이것이 정말로 글로벌해야하는지 스스로에게 물어보십시오. f그냥 자유 함수가 아닌 인스턴스 메서드로 클래스를 원 할까요? 그런 다음 다음과 같이 할 수 있습니다.

import module1
thingy1 = module1.Thingy(a=3)
thingy1.f()

정말로 전역을 원하지만에서 사용하기 위해 거기에 있다면 module1해당 모듈에서 설정하십시오.

import module1
module1.a=3
module1.f()

반면에 a많은 모듈에서 공유되는 경우 다른 곳에 배치하고 모두가 가져 오도록합니다.

import shared_stuff
import module1
shared_stuff.a = 3
module1.f()

… 그리고 module1.py에서 :

import shared_stuff
def f():
    print shared_stuff.a

from변수가 상수가 아닌 경우 가져 오기를 사용 하지 마십시오 . 가져올 때 참조 된 항목으로 초기화 from shared_stuff import a된 새 a변수를 만들고이 shared_stuff.aa변수는에 대한 할당의 영향을받지 않습니다 shared_stuff.a.


또는 드문 경우에 내장 모듈과 같이 모든 곳에서 진정으로 전역 적이어야하는 경우 내장 모듈에 추가하십시오. 정확한 세부 사항은 Python 2.x와 3.x간에 다릅니다. 3.x에서는 다음과 같이 작동합니다.

import builtins
import module1
builtins.a = 3
module1.f()


답변

해결 방법으로 다음과 같이 외부 계층에서 환경 변수를 설정하는 것을 고려할 수 있습니다.

main.py :

import os
os.environ['MYVAL'] = str(myintvariable)

mymodule.py :

import os

myval = None
if 'MYVAL' in os.environ:
    myval = os.environ['MYVAL']

추가 예방 조치로 MYVAL이 모듈 내부에 정의되어 있지 않은 경우 처리하십시오.


답변

함수는 정의 된 모듈의 전역을 사용합니다 . a = 3예를 들어 를 설정하는 대신을 설정 해야합니다 module1.a = 3. 따라서에서 cur글로벌로 utilities_module사용하려면utilities_module.cur .

더 나은 해결책 : 전역을 사용하지 마십시오. 필요한 변수를 필요한 함수에 전달하거나 모든 데이터를 함께 묶는 클래스를 만들고 인스턴스를 초기화 할 때 전달합니다.


답변

이 게시물은 내가 만난 Python 동작에 대한 관찰 일뿐입니다. 위에서 읽은 조언이 아래에서했던 것과 똑같은 일을했다면 효과가 없을 수도 있습니다.

즉, 전역 / 공유 변수를 포함하는 모듈이 있습니다 (위에서 제안한대로).

#sharedstuff.py

globaltimes_randomnode=[]
globalist_randomnode=[]

그런 다음 공유 항목을 가져 오는 기본 모듈이 있습니다.

import sharedstuff as shared

그리고 실제로 이러한 어레이를 채운 다른 모듈. 이들은 메인 모듈에 의해 호출됩니다. 이러한 다른 모듈을 종료 할 때 어레이가 채워져 있음을 분명히 알 수 있습니다. 그러나 기본 모듈에서 다시 읽을 때 비어 있습니다. 이것은 나에게 다소 이상했습니다 (글쎄요, 저는 Python을 처음 사용했습니다). 그러나 주 모듈에서 sharedstuff.py를 가져 오는 방법을 다음과 같이 변경하면

from globals import *

작동했습니다 (배열이 채워졌습니다).

그냥 말해


답변

이 특정 문제에 대한 가장 쉬운 해결책은 모듈 전역의 변수에 커서를 저장했을 모듈 내에 다른 함수를 추가하는 것입니다. 그러면 다른 모든 기능도 사용할 수 있습니다.

module1 :

cursor = None

def setCursor(cur):
    global cursor
    cursor = cur

def method(some, args):
    global cursor
    do_stuff(cursor, some, args)

주요 프로그램 :

import module1

cursor = get_a_cursor()
module1.setCursor(cursor)
module1.method()


답변

전역은 모듈에 따라 다르기 때문에 가져온 모든 모듈에 다음 함수를 추가 한 다음 사용할 수 있습니다.

  • 단일 변수 (사전 형식)를 전역 변수로 추가합니다.
  • 메인 모듈 전역을 그것으로 전송하십시오 .

addglobals = 람다 x : globals (). update (x)

그런 다음 현재 전역에 전달해야하는 것은 다음과 같습니다.

가져 오기 모듈

module.addglobals (globals ())


답변

위의 답변에서 보지 global_dict못했기 때문에 호출 모듈의 전역을 필요로하는 함수에 인수를 추가 한 다음 호출 할 때 함수에 dict를 전달하는 간단한 해결 방법을 추가 할 것이라고 생각했습니다 . 예 :

# external_module
def imported_function(global_dict=None):
    print(global_dict["a"])


# calling_module
a = 12
from external_module import imported_function
imported_function(global_dict=globals())

>>> 12