언제 Flask.g을 사용해야합니까?


173

I g 나를 만든 플라스크 0.10에 응용 프로그램 컨텍스트에 요청 문맥에서 이동은,의 용도에 대해 혼란스러워 g.

Flask 0.9의 이해는 다음과 같습니다.

  • g 요청 컨텍스트에 존재합니다. 즉, 요청이 시작될 때 새로 생성되고 끝날 때까지 사용 가능
  • g내가 요청의 기간 동안 관련 물건을 넣을 수있는 "요청 칠판"로 사용하기위한 것입니다 (즉, 요청의 시작 부분에 플래그를 설정하고부터 가능, 마지막에 처리 before_request/의 after_request쌍)
  • 요청 수준 상태를 유지하는 것 외에도 g데이터베이스 연결을 유지하는 등 리소스 관리에 사용할 수 있으며 사용해야합니다.

Flask 0.10에서 더 이상 해당되지 않는 문장은 무엇입니까? 누군가 변경 이유 를 논의하는 리소스를 알려줄 수 있습니까? Flask 0.10에서 "요청 칠판"으로 무엇을 사용해야합니까? 내 자신의 앱 / 확장자 별 스레드 로컬 프록시를 작성하여 컨텍스트 스택으로 푸시해야 before_request합니까? 내 응용 프로그램이 오랜 기간 동안 (요청이 아닌) 지속되어 리소스가 해제되지 않는 경우 응용 프로그램 컨텍스트에서 리소스 관리의 요점은 무엇입니까?


나는 이것이 매우 이상한 변화라는 데 동의합니다. 바라건대 mitsuhiko g는 0.10에서 대체 할 일종의 요청 컨텍스트 객체를 구현합니다 . 그렇지 않으면 많은 코드가 악의적 인 버그를 개발하기 시작할 수 있습니다.
Anorov

11
FWIW, Armin Ronacher (Flask의 저자)는 new 사용 방법에 대한 예제 코드를 보여주는 "Advanced Flask Patterns"의 속편을 발표했습니다 flask.g. speakerdeck.com/mitsuhiko/advanced-flask-patterns-1
Markus Unterwaditzer

1
또한 새로운 요청 컨텍스트는 새로운 앱 컨텍스트를 의미하므로 정상적인 사용시에는 정상적으로 작동합니다
Ronny

답변:


119

Markus연결된 Advanced Flask Patternsg 는 0.10의 일부 변경 사항을 설명합니다 .

  • g 이제 응용 프로그램 컨텍스트에 있습니다.
  • 모든 요청은 새로운 애플리케이션 컨텍스트를 푸시 하고 이전 컨텍스트 를 삭제하므로 g코드를 변경하지 않고도 요청 당 플래그를 설정하는 데 계속 사용할 수 있습니다.
  • 응용 프로그램 컨텍스트 가 호출 된 팝업 teardown_request됩니다. (아르 민의 발표는 DB 연결을 만드는 등의 일을하는 작업이기 때문입니다 설명 설치 요청에 대한 환경 및 내부 처리해서는 안 before_request하고 after_request)

링크 된 소스 코드에서 app_ctx is None or app_ctx.app != self.appFalse는 언제 입니까? 오래된 응용 프로그램 컨텍스트가 재사용되는 것 같습니다. 응용 프로그램 컨텍스트가 "요청간에 공유되지 않을 것"이기 때문에 이것은 옳지 않은 것 같습니다 ...
nalzok

2
추진app.app_context() 을 언급하고 있습니까? 그렇다면, app_context()매번 호출 할 때마다 새로운 애플리케이션 컨텍스트를 인스턴스화합니다. 컨텍스트를 재사용하지 않습니다.
theY4Kman

1
예 그 사실이지만 때 app_ctx is not None and app_ctx.app == self.appapp_ctx = self.app.app_context()라인이되어 있지 실행; self._implicit_app_ctx_stack.append(None)이 경우 에만 실행됩니다.
nalzok

1
아 죄송합니다 프로덕션 설정에서는 스레드 (또는 그린 릿) 당 하나의 요청 만 제공됩니다. 하나만 RequestContext푸시되므로 하나만 AppContext푸시됩니다. 그러나 디버그 모드가 켜져 있고 요청이 실패하면 Flask는 컨텍스트를 저장 하므로 디버거와 함께 사용할 수 있습니다 . None에 추가 _app_ctx_stack되므로 요청이 중단되면 AppContext아직 팝업되지 않습니다 . 테스트 클라이언트에서도 동일한 상황이 발생하여 컨텍스트를 유지하므로 검사 할 수 있습니다.
theY4Kman

따라서 g의 범위는 요청 당 (스레드)이며 후속 요청에서 값을 유지하지 않습니다.
변수

83

이 글의 정보에 대한 부록으로서 : flask.g저 역시 그 동작에 약간 혼란 스러웠지만 , 몇 가지 빠른 테스트를 통해이를 명확히하는 데 도움이되었습니다. 내가 시도한 것은 다음과 같습니다.

from flask import Flask, g
app = Flask(__name__)

with app.app_context():
    print('in app context, before first request context')
    print('setting g.foo to abc')
    g.foo = 'abc'
    print('g.foo should be abc, is: {0}'.format(g.foo))

    with app.test_request_context():
        print('in first request context')
        print('g.foo should be abc, is: {0}'.format(g.foo))
        print('setting g.foo to xyz')
        g.foo = 'xyz'
        print('g.foo should be xyz, is: {0}'.format(g.foo))

    print('in app context, after first request context')
    print('g.foo should be abc, is: {0}'.format(g.foo))

    with app.test_request_context():
        print('in second request context')
        print('g.foo should be abc, is: {0}'.format(g.foo))
        print('setting g.foo to pqr')
        g.foo = 'pqr'
        print('g.foo should be pqr, is: {0}'.format(g.foo))

    print('in app context, after second request context')
    print('g.foo should be abc, is: {0}'.format(g.foo))

그리고 그 결과는 다음과 같습니다.

in app context, before first request context
setting g.foo to abc
g.foo should be abc, is: abc  

in first request context
g.foo should be abc, is: abc
setting g.foo to xyz
g.foo should be xyz, is: xyz  

in app context, after first request context
g.foo should be abc, is: xyz  

in second request context
g.foo should be abc, is: xyz
setting g.foo to pqr
g.foo should be pqr, is: pqr  

in app context, after second request context
g.foo should be abc, is: pqr

Y4Kman이 위에서 말했듯이 "모든 요청은 새로운 애플리케이션 컨텍스트를 제공합니다". 그리고 플라스크 문서가 말한대로 , 애플리케이션 컨텍스트는 "요청 사이에 공유되지 않습니다." 이제 명시 적으로 언급되지 않은 것은 (이 문장에서 암시한다고 생각하지만) 내 테스트에서 분명히 보여주는 것은 하나의 응용 프로그램 컨텍스트 안에 중첩 된 여러 요청 컨텍스트를 명시 적으로 생성 해서는 안된다는flask.g 것입니다. 응용 프로그램과 요청 수준에 독립적으로 존재하는 서로 다른 상태로 두 가지 다른 "수준"컨텍스트에서 작동하는 마술이 없습니다.

때문에 현실은, 그 "응용 프로그램 컨텍스트가"잠재적으로 매우 잘못된 이름입니다 app.app_context() 입니다 당 요청 컨텍스트 는 AS 정확히 같은, "요청 컨텍스트" . 일반적으로 요청 컨텍스트가 필요한 일부 변수가 필요하지만 요청 오브젝트에 액세스 할 필요가없는 경우 (예 : 배치 DB 작업을 실행하는 경우)에만 필요한 "요청 컨텍스트 라이트"로 생각하십시오. 쉘 스크립트). 하나 이상의 요청 컨텍스트를 포함하도록 응용 프로그램 컨텍스트를 확장하려고하면 문제가 발생합니다. 따라서 위의 테스트 대신 Flask의 컨텍스트를 사용하여 이와 같은 코드를 작성해야합니다.

from flask import Flask, g
app = Flask(__name__)

with app.app_context():
    print('in app context, before first request context')
    print('setting g.foo to abc')
    g.foo = 'abc'
    print('g.foo should be abc, is: {0}'.format(g.foo))

with app.test_request_context():
    print('in first request context')
    print('g.foo should be None, is: {0}'.format(g.get('foo')))
    print('setting g.foo to xyz')
    g.foo = 'xyz'
    print('g.foo should be xyz, is: {0}'.format(g.foo))

with app.test_request_context():
    print('in second request context')
    print('g.foo should be None, is: {0}'.format(g.get('foo')))
    print('setting g.foo to pqr')
    g.foo = 'pqr'
    print('g.foo should be pqr, is: {0}'.format(g.foo))

예상되는 결과는 다음과 같습니다.

in app context, before first request context
setting g.foo to abc
g.foo should be abc, is: abc  

in first request context
g.foo should be None, is: None
setting g.foo to xyz
g.foo should be xyz, is: xyz  

in second request context
g.foo should be None, is: None
setting g.foo to pqr
g.foo should be pqr, is: pqr

7
마지막 문단으로 인해 상향 조정 된 플라스크의 상황은 처음에는 이해하기가 매우 혼란 스럽습니다. 이름에서 요청 컨텍스트는 요청 당이며 앱 컨텍스트는 요청 후에도 존재하거나 수명에 영향을받지 않는다는 느낌을받습니다.
simanacci
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.