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.a
새 a
변수는에 대한 할당의 영향을받지 않습니다 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