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

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

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

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

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



답변

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

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

답변

이 글의 정보에 대한 부록으로서 : 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


답변