programing

가져온 모듈에서 전역 변수의 가시성

iphone6s 2023. 6. 21. 22:25
반응형

가져온 모듈에서 전역 변수의 가시성

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

일부 유틸리티 함수/클래스를 정의한 모듈이 있다고 가정해 보겠습니다. 이는 이 보조 모듈을 가져올 네임스페이스에 정의된 엔티티를 나타냅니다("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

반응형