From d11604a78dbb798069ed27b92ec36f7d47d35392 Mon Sep 17 00:00:00 2001 From: tasoo park Date: Sun, 17 Nov 2024 03:34:16 +0900 Subject: [PATCH 1/2] =?UTF-8?q?fixed=20#58:=20session=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pykis/kis.py | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/pykis/kis.py b/pykis/kis.py index bbe67325..7feb2f11 100644 --- a/pykis/kis.py +++ b/pykis/kis.py @@ -421,6 +421,16 @@ def __init__( else KisAccessToken.load(virtual_token) if self.virtual and virtual_token else None ) + self._sessions = { + "real": requests.Session(), + "virtual": requests.Session() + } + + for session in self._sessions.values(): + session.headers.update({ + "User-Agent": USER_AGENT + }) + if keep_token: if keep_token is True: keep_token = get_cache_path() @@ -516,11 +526,11 @@ def request( elif body is None: body = {} - if headers is None: - headers = {} + request_headers = headers.copy() if headers else {} if domain is None: domain = "virtual" if self.virtual else "real" + session = self._sessions[domain] if appkey_location: appkey = self.appkey if domain == "real" else self.virtual_appkey @@ -528,32 +538,30 @@ def request( if appkey is None: raise ValueError("모의도메인 AppKey가 없습니다.") - appkey.build(headers if appkey_location == "header" else body) + appkey.build(request_headers if appkey_location == "header" else body) if form is not None: if form_location is None: form_location = "params" if method == "GET" else "body" - dist = headers if form_location == "header" else params if form_location == "params" else body + dist = request_headers if form_location == "header" else params if form_location == "params" else body for f in form: if f is not None: f.build(dist) - headers["User-Agent"] = USER_AGENT - rate_limit = self._rate_limiters[domain] while True: rate_limit.acquire(blocking_callback=self._rate_limit_exceeded) if auth: - (self.token if domain == "real" else self.primary_token).build(headers) + (self.token if domain == "real" else self.primary_token).build(request_headers) - resp = requests.request( + resp = session.request( method=method, url=urljoin(REAL_DOMAIN if domain == "real" else VIRTUAL_DOMAIN, path), - headers=headers, + headers=request_headers, params=params, json=body, ) @@ -563,7 +571,7 @@ def request( try: data = resp.json() - except: + except Exception: data = None error_code = data.get("msg_cd") if data is not None else None @@ -579,8 +587,10 @@ def request( # Token expired if domain == "real": self._token = None + self._sessions["real"].headers.pop('Authorization', None) else: self._virtual_token = None + self._sessions["virtual"].headers.pop('Authorization', None) case _: raise KisHTTPError(response=resp) @@ -731,6 +741,11 @@ def websocket(self) -> KisWebsocketClient: return self._websocket + def __del__(self): + """API 세션을 종료합니다.""" + for session in self._sessions.values(): + session.close() + from pykis.api.stock.trading_hours import trading_hours from pykis.scope.account import account - from pykis.scope.stock import stock + from pykis.scope.stock import stock \ No newline at end of file From 3590fdb54f9522651ea38bcde08073bd824365b5 Mon Sep 17 00:00:00 2001 From: Soju06 Date: Mon, 25 Nov 2024 14:56:45 +0900 Subject: [PATCH 2/2] chore: add type annotations to session property --- pykis/kis.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/pykis/kis.py b/pykis/kis.py index 7feb2f11..acd36acd 100644 --- a/pykis/kis.py +++ b/pykis/kis.py @@ -61,6 +61,8 @@ def virtual(self) -> bool: """웹소켓 클라이언트""" _keep_token: Path | None """API 접속 토큰 자동 저장 경로""" + _sessions: dict[Literal["real", "virtual"], requests.Session] + """API 세션""" @property def keep_token(self) -> bool: @@ -420,16 +422,13 @@ def __init__( if isinstance(virtual_token, KisAccessToken) else KisAccessToken.load(virtual_token) if self.virtual and virtual_token else None ) - self._sessions = { "real": requests.Session(), - "virtual": requests.Session() + "virtual": requests.Session(), } for session in self._sessions.values(): - session.headers.update({ - "User-Agent": USER_AGENT - }) + session.headers.update({"User-Agent": USER_AGENT}) if keep_token: if keep_token is True: @@ -530,6 +529,7 @@ def request( if domain is None: domain = "virtual" if self.virtual else "real" + session = self._sessions[domain] if appkey_location: @@ -587,10 +587,8 @@ def request( # Token expired if domain == "real": self._token = None - self._sessions["real"].headers.pop('Authorization', None) else: self._virtual_token = None - self._sessions["virtual"].headers.pop('Authorization', None) case _: raise KisHTTPError(response=resp) @@ -741,11 +739,15 @@ def websocket(self) -> KisWebsocketClient: return self._websocket - def __del__(self): + def close(self) -> None: """API 세션을 종료합니다.""" for session in self._sessions.values(): session.close() + def __del__(self) -> None: + """API 세션을 종료합니다.""" + self.close() + from pykis.api.stock.trading_hours import trading_hours from pykis.scope.account import account - from pykis.scope.stock import stock \ No newline at end of file + from pykis.scope.stock import stock