가져온 모듈에서 전역 변수의 가시성
파이썬 스크립트에서 모듈을 가져오는 벽에 부딪혔습니다.오류를 설명하기 위해 최선을 다하겠습니다. 오류가 발생한 이유와 문제를 해결하기 위해 이 특정 접근 방식을 사용하는 이유를 설명합니다(잠시 후에 설명하겠습니다.
일부 유틸리티 함수/클래스를 정의한 모듈이 있다고 가정해 보겠습니다. 이는 이 보조 모듈을 가져올 네임스페이스에 정의된 엔티티를 나타냅니다("a"가 이러한 엔티티일 경우).
모듈 1:
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
유사한 질문이 과거에 (이틀 전에) 제기되었고 몇 가지 해결책이 제안되었지만, 저는 이것들이 제 요구 사항에 부합하지 않는다고 생각합니다.다음은 제 특별한 맥락입니다.
저는 MySQL 데이터베이스 서버에 연결하여 GUI로 데이터를 표시/수정하는 파이썬 프로그램을 만들려고 합니다.청결을 위해, 저는 보조/유틸리티 MySQL 관련 함수들의 묶음을 별도의 파일로 정의했습니다.그러나 이들은 모두 공통 변수를 가지고 있는데, 이 변수는 제가 원래 유틸리티 모듈 내부에 정의한 것이며 MySQLDB 모듈의 커서 개체입니다.나중에 알게 된 것은 메인 모듈에 커서 객체(DB 서버와 통신하는 데 사용됨)를 정의해야 메인 모듈과 메인 모듈로 가져온 모든 것이 해당 객체에 액세스할 수 있다는 것입니다.
최종 결과는 다음과 같습니다.
utilities_message.py:
def utility_1(args):
code which references a variable named "cur"
def utility_n(args):
etcetera
그리고 제 주요 모듈은:
프로그램.py:
import MySQLdb, Tkinter
db=MySQLdb.connect(#blahblah) ; cur=db.cursor() #cur is defined!
from utilities_module import *
그런 다음 유틸리티 함수를 호출하려고 하면 위에서 언급한 "global name not defined" 오류가 발생합니다.
유틸리티 파일에 다음과 같은 "from program import cur" 문을 사용하는 것이 좋습니다.
utilities_message.py:
from program import cur
#rest of function definitions
프로그램.py:
import Tkinter, MySQLdb
db=MySQLdb.connect(#blahblah) ; cur=db.cursor() #cur is defined!
from utilities_module import *
하지만 그것은 순환적인 수입이거나 비슷한 것이고, 결론적으로, 그것은 붕괴합니다.그래서 제 질문은:
기본 모듈에 정의된 "커" 개체를 가져온 보조 기능에 표시하려면 어떻게 해야 합니까?
시간을 내주셔서 감사드리며, 솔루션이 다른 곳에 게시된 경우에는 깊은 사과를 드립니다.저 자신도 답을 찾을 수가 없어서 책에 더 이상 요령이 없습니다.
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()
모듈 1에 포함됩니다.py:
import shared_stuff
def f():
print shared_stuff.a
사용 안 함from변수를 상수로 지정하지 않은 경우 가져오기를 수행합니다. from shared_stuff import a새로운 것을 만들 것입니다.a으로 shared_stuff.a과 이 가져기당참내용조된시, 이새것운로그고리오▁referred것▁new새운로,이.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)
나의 모듈py:
import os
myval = None
if 'MYVAL' in os.environ:
myval = os.environ['MYVAL']
추가 예방 조치로 모듈 내부에 MYVAL이 정의되어 있지 않은 경우 처리합니다.
이 게시물은 제가 접한 파이썬 행동에 대한 관찰일 뿐입니다.아마도 당신이 위에서 읽은 조언들은 당신에게 효과가 없을 것입니다. 만약 당신이 아래에서 했던 것과 같은 것을 만들었다면.
즉, 위에서 제안한 대로 글로벌/공유 변수가 포함된 모듈이 있습니다.
#sharedstuff.py
globaltimes_randomnode=[]
globalist_randomnode=[]
그런 다음 공유 항목을 가져오는 메인 모듈을 사용했습니다.
import sharedstuff as shared
그리고 이 어레이를 실제로 사용한 다른 모듈들도 있습니다.이것들은 메인 모듈에 의해 호출됩니다.이러한 다른 모듈을 종료하면 어레이가 채워져 있음을 명확하게 알 수 있습니다.하지만 메인 모듈에서 다시 읽어보니 비어 있었습니다.이것은 저에게 다소 이상했습니다(글쎄요, 저는 파이썬이 처음입니다).그러나 기본 모듈에서 sharedstuff.py 을 가져오는 방법을 변경하면 다음과 같습니다.
from globals import *
작동했습니다(어레이가 채워짐).
그냥 하는 말
함수는 정의된 모듈의 전역을 사용합니다.설정 대신a = 3예를 들어, 당신은 설정해야 합니다.module1.a = 3그래서, 당신이 원한다면,cur에서 글로벌로 이용 가능한.utilities_module,세트utilities_module.cur.
더 나은 해결책은 글로벌을 사용하지 않는 것입니다.필요한 변수를 필요한 함수에 전달하거나 클래스를 만들어 모든 데이터를 함께 묶은 후 인스턴스를 초기화할 때 전달합니다.
이 특정 문제에 대한 가장 쉬운 해결책은 모듈 내에 커서를 모듈의 전역 변수에 저장하는 다른 함수를 추가하는 것입니다.그러면 다른 모든 기능도 사용할 수 있습니다.
모듈 1:
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()
글로벌은 모듈별로 다르므로 가져온 모든 모듈에 다음 기능을 추가한 다음 이 기능을 사용할 수 있습니다.
- 단일 변수(사전 형식)를 해당 변수에 대한 전역으로 추가합니다.
- 메인 모듈 글로벌을 전송합니다.
전역 추가 = 람다 x: 전역().업데이트(x)
그러면 현재 글로벌을 전달하기만 하면 됩니다.
가져오기 모듈
module.add 전역(수평)
갱신하다
이론을 테스트하기 위해 모듈을 만들어 Pypi에 붙였습니다.모든 것이 완벽하게 작동했습니다.
pip install superglobals
단답형
이것은 Python 2 또는 3에서 잘 작동합니다.
import inspect
def superglobals():
_globals = dict(inspect.getmembers(
inspect.stack()[len(inspect.stack()) - 1][0]))["f_globals"]
return _globals
로 저장.superglobals.py따라서 다른 모듈에 사용합니다.
from superglobals import *
superglobals()['var'] = value
확장 응답
당신은 물건을 더 매력적으로 만들기 위해 몇 가지 추가 기능을 추가할 수 있습니다.
def superglobals():
_globals = dict(inspect.getmembers(
inspect.stack()[len(inspect.stack()) - 1][0]))["f_globals"]
return _globals
def getglobal(key, default=None):
"""
getglobal(key[, default]) -> value
Return the value for key if key is in the global dictionary, else default.
"""
_globals = dict(inspect.getmembers(
inspect.stack()[len(inspect.stack()) - 1][0]))["f_globals"]
return _globals.get(key, default)
def setglobal(key, value):
_globals = superglobals()
_globals[key] = value
def defaultglobal(key, value):
"""
defaultglobal(key, value)
Set the value of global variable `key` if it is not otherwise st
"""
_globals = superglobals()
if key not in _globals:
_globals[key] = value
그런 다음 다음과 같이 사용합니다.
from superglobals import *
setglobal('test', 123)
defaultglobal('test', 456)
assert(getglobal('test') == 123)
정당성
이 질문을 엉망으로 만드는 "파이톤 순도 리그" 답변은 완벽하게 옳지만, 기본적으로 글로벌 인스턴스화된 대형 API로 단일 스레드화된 일부 환경(예: IDA Python)에서는 그다지 중요하지 않습니다.
그것은 여전히 나쁜 형태이고 격려하는 나쁜 관행이지만, 때때로 그것은 그저 더 쉽습니다.특히 당신이 쓰고 있는 코드의 수명이 그리 길지 않을 때는 더욱 그렇습니다.
위의 답변에서 본 적이 없기 때문에 간단한 해결 방법을 추가하려고 생각했습니다. 여기에는 다음과 같은 내용이 추가되었습니다.global_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
OOP 방법은 바인딩되지 않은 메서드 집합 대신 모듈을 클래스로 만드는 것입니다.그러면 당신은 사용할 수 있습니다.__init__또는 모듈 메소드에 사용할 변수를 호출자로부터 설정하는 세터 메소드입니다.
언급URL : https://stackoverflow.com/questions/15959534/visibility-of-global-variables-in-imported-modules
'programing' 카테고리의 다른 글
| Oracle SQL - 주별 데이터 합계 및 그룹화 (0) | 2023.06.21 |
|---|---|
| 함수 포인터와 컨텍스트를 예상하는 C-콜백에 C++ 람다를 전달하려면 어떻게 해야 합니까? (0) | 2023.06.21 |
| 현대 각도에서 손자부터 조부모까지 이벤트를 발산하는 방법은 무엇입니까? (0) | 2023.06.21 |
| MongoDB 3.6.2 2008 R2 Plus가 설치되지 않음 (0) | 2023.06.21 |
| 모두 제거모두 제거쿼리가 있는 태그 (0) | 2023.06.21 |