Aiohttp: μ‹€μ œ μ•±μœΌλ‘œ ν΄λΌμ΄μ–ΈνŠΈ 루프 였λ₯˜ ν…ŒμŠ€νŠΈ

에 λ§Œλ“  2018λ…„ 08μ›” 17일  Β·  4μ½”λ©˜νŠΈ  Β·  좜처: aio-libs/aiohttp

κΈ΄ 이야기 짧은

μ œμ•ˆλœ ν…ŒμŠ€νŠΈ νŒ¨ν„΄μ—λŠ” μ•± μ½”λ“œμ˜ μƒμš©κ΅¬ 쀑볡이 ν•„μš”ν•˜λ©° μ•± ν…ŒμŠ€νŠΈλ₯Ό 직접 ν‘œμ‹œν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

https://docs.aiohttp.org/en/stable/testing.html#pytest

μ˜ˆμƒλ˜λŠ” 행동

λ‚΄ 앱을 ν…ŒμŠ€νŠΈν•˜λ €λ©΄ λ‚΄ μ•± λͺ¨λ“ˆμ„ test_client 에 직접 전달할 수 μžˆμ–΄μ•Ό ν•©λ‹ˆλ‹€.

μ‹€μ œ 행동

λ¬Έμ„œλŠ” 각 ν…ŒμŠ€νŠΈ 전에 μ¦‰μ„μ—μ„œ ν•Έλ“€λŸ¬μ—μ„œ 앱을 λΉŒλ“œν•˜λŠ” 방법을 λ³΄μ—¬μ€λ‹ˆλ‹€. μ‹€μ œ app λ₯Ό test_client app 직접 μ „λ‹¬ν•˜λ©΄ μ²˜μŒμ—λŠ” μ œλŒ€λ‘œ μž‘λ™ν•œ λ‹€μŒ "RuntimeError: web.Application instance initialized with different loop"와 ν•¨κ»˜ μ‹€νŒ¨ν•©λ‹ˆλ‹€.

μž¬ν˜„ 단계

# handler.py

async def foo():
    return 'foo'
# app.py

from aiohttp import web
from .handler import foo

app = web.Application()
app.add_routes([web.get('/foo/', foo)])
# test.py

from .app import app

async def test_foo_status(test_client):
    response = await client.get('/foo/')
    assert response.status == 200

async def test_foo_body(test_client):
    response = await client.get('/foo/')
    body = await response.text()
    assert body == 'foo'

κ·€ν•˜μ˜ ν™˜κ²½

  • 운영 체제: μš°λΆ„νˆ¬ 18.04
  • 파이썬: 3.6.5
  • μ•„μ΄μ˜€http: 3.3.2

ν•΄κ²°

λ‚˜λŠ” μ§€κΈˆ μ†ŒμŠ€ μ½”λ“œλ₯Ό 엿보고 였λ₯˜μ˜ 원인을 νŒŒμ•…ν•˜μ—¬ 문제λ₯Ό ν•΄κ²°ν–ˆμŠ΅λ‹ˆλ‹€.

        if self._loop is not None and self._loop is not loop:
            raise RuntimeError(
                "web.Application instance initialized with different loop")

https://github.com/aio-libs/aiohttp/blob/e561eaa/aiohttp/web_app.py#L134

이 μ½”λ“œκ°€ ν•„μš”ν•œ μ΄μœ λŠ” μ¦‰μ‹œ λͺ…ν™•ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. μžμ‹ κΈ°λ‘μ—μ„œ μ»¨ν…μŠ€νŠΈλ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€. λ‚΄ ν…ŒμŠ€νŠΈ 정리 λ°©λ²•μ—μ„œ app._loop = None λ₯Ό μ„€μ •ν•˜λ©΄ 뢀정적인 λΆ€μž‘μš© 없이 문제λ₯Ό ν”Όν•  수 μžˆλŠ” 것 κ°™μŠ΅λ‹ˆλ‹€. 이 μ½”λ“œκ°€ μ‹€μ œλ‘œ ν•„μš”ν•œκ°€μš”? 이 μˆ˜μ • 사항을 test_client 톡합할 수 μžˆμŠ΅λ‹ˆκΉŒ?

outdated

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

Application λŠ” μƒνƒœ μ €μž₯ κ°œμ²΄μ΄λ―€λ‘œ λ‹¨μœ„ ν…ŒμŠ€νŠΈ λͺ¨μŒμ˜ λͺ¨λ“  ν…ŒμŠ€νŠΈμ— λŒ€ν•΄ λ‹€μ‹œ λ§Œλ“€μ–΄μ•Ό ν•©λ‹ˆλ‹€.
μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ 수λͺ…은 이벀트 λ£¨ν”„μ˜ 수λͺ…보닀 짧아야 ν•©λ‹ˆλ‹€.

힌트: app.app λ₯Ό ν˜ΈμΆœν•  λ•Œλ§ˆλ‹€ μƒˆ 앱을 λ°˜ν™˜ν•˜λŠ” async def app.make_app() μ½”λ£¨ν‹΄μœΌλ‘œ λ°”κΎΈμ„Έμš”.

λͺ¨λ“  4 λŒ“κΈ€

Application λŠ” μƒνƒœ μ €μž₯ κ°œμ²΄μ΄λ―€λ‘œ λ‹¨μœ„ ν…ŒμŠ€νŠΈ λͺ¨μŒμ˜ λͺ¨λ“  ν…ŒμŠ€νŠΈμ— λŒ€ν•΄ λ‹€μ‹œ λ§Œλ“€μ–΄μ•Ό ν•©λ‹ˆλ‹€.
μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ 수λͺ…은 이벀트 λ£¨ν”„μ˜ 수λͺ…보닀 짧아야 ν•©λ‹ˆλ‹€.

힌트: app.app λ₯Ό ν˜ΈμΆœν•  λ•Œλ§ˆλ‹€ μƒˆ 앱을 λ°˜ν™˜ν•˜λŠ” async def app.make_app() μ½”λ£¨ν‹΄μœΌλ‘œ λ°”κΎΈμ„Έμš”.

def make_app() 을 app.py ν•˜μ‹œκ² μŠ΅λ‹ˆκΉŒ? 그것은 μ˜λ―Έκ°€ μžˆμŠ΅λ‹ˆλ‹€.

FWIW ν† λ„€μ΄λ„λŠ” 첫 번째 μ˜ˆμ—μ„œ make_app() νŒ¨ν„΄μ„ μ΄‰μ§„ν•©λ‹ˆλ‹€. ν…ŒμŠ€νŠΈ νŒŒμΌμ—μ„œ 앱을 μ‘°λ‘±ν•˜λŠ” 것은 λ¬Έμ„œκ°€ ν™λ³΄ν•˜κΈ°μ— 쒋은 νŒ¨ν„΄μ΄ μ•„λ‹ˆλΌκ³  μƒκ°ν•©λ‹ˆλ‹€.

http://www.tornadoweb.org/en/stable/#hello -world

μ†”μ§νžˆ μ €λŠ” aiohttp 개체λ₯Ό μ‘°λ‘±ν•˜λŠ” 것이 쒋은 νŒ¨ν„΄μ΄λΌκ³  μƒκ°ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

이 μŠ€λ ˆλ“œλŠ” λ‹«νžŒ ν›„ 졜근 ν™œλ™μ΄ μ—†μ—ˆκΈ° λ•Œλ¬Έμ— μžλ™μœΌλ‘œ μž κ²ΌμŠ΅λ‹ˆλ‹€. κ΄€λ ¨ λ²„κ·ΈλŠ” [μ‹ κ°„ν˜Έ]λ₯Ό μ—΄μ–΄μ£Όμ„Έμš”.
이 ν† λ‘ μ—μ„œ μ€‘μš”ν•œ μš”μ μ΄ μžˆλ‹€κ³  μƒκ°λ˜λ©΄ ν•΄λ‹Ή λ‚΄μš©μ„ [μƒˆ 문제]에 ν¬ν•¨μ‹œν‚€μ‹­μ‹œμ˜€.

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰