2525from tigeropen .common .util .signature_utils import get_sign_content , sign_with_rsa , verify_with_rsa
2626from tigeropen .common .util .web_utils import do_post
2727
28- try :
29- from getmac import get_mac_address
30- except ImportError :
31- def get_mac_address ():
32- return ':' .join (("%012x" % uuid .getnode ())[i :i + 2 ] for i in range (0 , 12 , 2 ))
3328
3429LOG_FORMATTER = logging .Formatter ('%(asctime)s %(name)s %(levelname)s: %(message)s' )
3530SKIP_RETRY_SERVICES = {PLACE_ORDER , CANCEL_ORDER , MODIFY_ORDER }
3631
37-
3832_SCHEDULE_STATE = {'is_running' : False }
3933
4034
@@ -43,6 +37,7 @@ class TigerOpenClient:
4337 client_config:客户端配置,包含tiger_id、应用私钥、老虎公钥等
4438 logger:日志对象,客户端执行信息会通过此日志对象输出
4539 """
40+
4641 def __init__ (self , client_config , logger = None ):
4742 self .__config = client_config
4843 if not client_config .private_key :
@@ -63,62 +58,56 @@ def __init__(self, client_config, logger=None):
6358 "Connection" : "Keep-Alive" ,
6459 "User-Agent" : 'openapi-python-sdk-' + __VERSION__
6560 }
66- self .__device_id = self .__get_device_id ()
67- self .__init_license ()
68- self .__refresh_server_info ()
69- if self .__config .token and self .__config .license :
70- self .__schedule_thread ()
61+ self ._initialize ()
62+
63+ def _initialize (self ):
64+ if not self .__config .inited :
65+ self .__logger .info (f'sdk version: { self .__config .sdk_version } ' )
66+ self .__init_license ()
67+ self .__refresh_server_info ()
68+ if self .__config .token and self .__config .license :
69+ self .__schedule_thread ()
70+ self .__config .inited = True
7171
7272 def __init_license (self ):
73+ self .__logger .debug ('init license' )
7374 if self .__config .license is None and self .__config .enable_dynamic_domain :
7475 self .__config .license = self .query_license ()
7576
7677 def __refresh_server_info (self ):
78+ self .__logger .debug ('init server info' )
7779 self .__config .refresh_server_info ()
7880
79-
80- """
81- 内部方法,从params中抽取公共参数
82- """
83-
8481 def __get_common_params (self , params ):
82+ """
83+ 内部方法,从params中抽取公共参数
84+ """
8585 common_params = dict ()
8686 common_params [P_TIMESTAMP ] = params [P_TIMESTAMP ]
8787 common_params [P_TIGER_ID ] = self .__config .tiger_id
8888 common_params [P_METHOD ] = params [P_METHOD ]
8989 common_params [P_CHARSET ] = self .__config .charset
9090 common_params [P_VERSION ] = params [P_VERSION ] if params .get (P_VERSION ) is not None else OPEN_API_SERVICE_VERSION
9191 common_params [P_SIGN_TYPE ] = self .__config .sign_type
92- common_params [P_DEVICE_ID ] = self .__device_id
92+ common_params [P_DEVICE_ID ] = self .__config . _device_id
9393 if has_value (params , P_NOTIFY_URL ):
9494 common_params [P_NOTIFY_URL ] = params [P_NOTIFY_URL ]
9595 return common_params
9696
97- @staticmethod
98- def __get_device_id ():
97+ def __remove_common_params (self , params ):
9998 """
100- 获取mac地址作为device_id
101- :return:
99+ 内部方法,从params中移除公共参数
102100 """
103- try :
104- return get_mac_address ()
105- except :
106- return None
107-
108- """
109- 内部方法,从params中移除公共参数
110- """
111- def __remove_common_params (self , params ):
112101 if not params :
113102 return
114103 for k in COMMON_PARAM_KEYS :
115104 if k in params :
116105 params .pop (k )
117106
118- """
119- 内部方法,通过请求request对象构造请求查询字符串和业务参数
120- """
121107 def __prepare_request (self , request , url = '' ):
108+ """
109+ 内部方法,通过请求request对象构造请求查询字符串和业务参数
110+ """
122111 THREAD_LOCAL .logger = self .__logger
123112 params = request .get_params ()
124113 params [P_TIMESTAMP ] = datetime .datetime .now ().strftime ("%Y-%m-%d %H:%M:%S" )
@@ -139,11 +128,10 @@ def __prepare_request(self, request, url=''):
139128
140129 return all_params
141130
142- """
143- 内部方法,解析请求返回结果并做验签
144- """
145-
146131 def __parse_response (self , response_str , timestamp = None ):
132+ """
133+ 内部方法,解析请求返回结果并做验签
134+ """
147135 response_str = response_str .decode (self .__config .charset )
148136 if THREAD_LOCAL .logger :
149137 THREAD_LOCAL .logger .debug ('[' + THREAD_LOCAL .uuid + ']response:' + response_str )
@@ -181,10 +169,10 @@ def _get_retry_deco(self, service):
181169 jitter = None )
182170 return None
183171
184- """
185- 执行接口请求
186- """
187172 def execute (self , request , url = None ):
173+ """
174+ 执行接口请求
175+ """
188176 if self .__config .token :
189177 self ._update_header ()
190178 if url is None :
@@ -196,7 +184,7 @@ def execute(self, request, url=None):
196184 retry_deco = self ._get_retry_deco (request ._method )
197185 if retry_deco is not None :
198186 response = retry_deco (do_post )(url , query_string , self .__headers , params , self .__config .timeout ,
199- self .__config .charset )
187+ self .__config .charset )
200188 else :
201189 response = do_post (url , query_string , self .__headers , params , self .__config .timeout ,
202190 self .__config .charset )
@@ -234,10 +222,11 @@ def query_token(self):
234222 return None
235223
236224 def refresh_token (self ):
225+ self .__config .token = self .__config .load_token ()
237226 new_token = self .query_token ()
238227 if new_token :
239228 self .__logger .info (f"refresh token, old:{ self .__config .token } , new:{ new_token } " )
240- self .__config .load_or_store_token (new_token )
229+ self .__config .store_token (new_token )
241230
242231 def __token_refresh_task (self ):
243232 try :
@@ -249,13 +238,38 @@ def __token_refresh_task(self):
249238 def __schedule_thread (self ):
250239 if not _SCHEDULE_STATE ['is_running' ] and self .__config .token_refresh_duration != 0 :
251240 _SCHEDULE_STATE ['is_running' ] = True
252- self .__logger .info ('Starting schedule thread...' )
241+ self .__logger .info ('Starting token refresh thread...' )
253242 daemon = RepeatTimer (self .__config .token_check_interval , self .__token_refresh_task )
254243 daemon .daemon = True
255244 daemon .start ()
245+ self .__monitor_token ()
246+
247+ def __monitor_token (self ):
248+ """对于多进程运行的情况,需监控token文件变动并加载,防止另一个进程刷新token后导致本进程token失效.
249+ 需安装watchdog实现此功能: pip install watchdog"""
250+ try :
251+ from watchdog .observers import Observer
252+ from watchdog .events import FileSystemEventHandler
253+ except ImportError :
254+ return
255+
256+ def on_modified (event ):
257+ file_token = self .__config .load_token ()
258+ if file_token != self .__config .token :
259+ self .__logger .info (f'load token from changed token file, old: { self .__config .token } , '
260+ f'new:{ file_token } ' )
261+ self .__config .token = file_token
262+
263+ event_handler = FileSystemEventHandler ()
264+ event_handler .on_modified = on_modified
265+ observer = Observer ()
266+ observer .schedule (event_handler , self .__config .get_token_path (), recursive = True )
267+ observer .daemon = True
268+ observer .start ()
269+ self .__logger .info ('Starting token monitor thread...' )
256270
257271
258272class RepeatTimer (Timer ):
259273 def run (self ):
260274 while not self .finished .wait (self .interval ):
261- self .function (* self .args , ** self .kwargs )
275+ self .function (* self .args , ** self .kwargs )
0 commit comments