1

error 1 и error 1003

(13/05/2019 10:37:15 отредактировано NeiroN)

Тема: error 1 и error 1003

Как корректно обрабатывать ошибки связанные со входом  и истекшей сессией?

Из-за непонимания алгоритма получил вечную рекурсию.

Пока код такой

# -*- coding: utf-8 -*-
from urllib.request import Request,urlopen,install_opener,build_opener,ProxyHandler
from urllib.parse import urlencode
import json,os,time


class Tracker:
    base_url = "https://hst-api.wialon.com"
    sid = None
    api_key = None
    object_ids = None
    def __init__(self,api_key,name,sid=None):
        #install_opener(build_opener(ProxyHandler({"http": "http://proxy:3128","https":"https://proxy:3128"})))
        self.api_key = api_key
        self.name = name
        self.sid = sid or self.login(api_key,name).sid
    def request(self,svc,params):
        data = urlencode({"sid":self.sid,"svc":svc,"params":json.dumps(params)},safe=":/{},")
        headers = {"Content-Type": "application/x-www-form-urlencoded; charset=utf-8","Content-Length": len(data)}
        try:
            with urlopen(Request(self.base_url+"/wialon/ajax.html",bytes(data,"utf-8"),headers),timeout=2) as resp:
                data = resp.read()
                print(data)
                if isinstance(data,bytes):data = str(data,'utf-8')
                data = json.loads(data)
                if isinstance(data,dict) and "error" in data.keys():#если истекла сессия то повторный логин и запрос
                    if data["error"] == 1:
                        self.login()
                    if data["error"] == 1003:
                        print("Waiting for wialon ready")
                        time.sleep(60)
                    if self.sid:
                        return self.request(svc,params)
                    return None
                else:
                    return data
        except:
            print("Wialon timeout")
            return None
    def login(self,api_key=None,name=None):
        #print("WialonLogin():%s"%self.sid)
        self.sid = None
        data = self.request("token/login",{"token":api_key or self.api_key,"operateAs":name or self.name})
        if data:
            if "error" in data:
                return self
            self.name = data["user"]["nm"]
            self.sid = data["eid"]
            objects = None
            if "mongr" in data["user"]["prp"].keys():
                gobjects = json.loads(data["user"]["prp"]["mongr"])
                objects = []
                for k,v in gobjects.items():
                    objects += v
            if "monu" in data["user"]["prp"].keys() and not objects:
                objects = json.loads(data["user"]["prp"]["monu"])
            #self.object_ids = [int(x) for x in objects]
            #print(self.object_ids)
            #self.object_params = self.track(self.object_ids)
        return self
    def objects(self,ids=None):
        #print("WialonObjects():%s"%self.sid)
        data = self.request("core/search_items",{"spec":{"itemsType":"avl_unit","propName":"id","propValueMask":"*","sortType":"id"},"force":1,"flags":4194321,"from":0,"to":0})
        if data:
            data = data["items"]
        else:
            return None
        objects = {}
        for i,v in enumerate(data):
            v["uri"] = os.path.basename(v["uri"]).replace("svg","png")
            if ids:
                if v["id"] in ids:
                    objects[v["id"]] = v
            else:
                objects[v["id"]] = v
        return objects
    def track(self,objects):
        return {x["i"]:x["d"] for x in self.request("core/update_data_flags",{"spec":[{"type":"col","data":objects,"flags":4194304,"mode":1}]})}
    def tokenList(self,user=None):
        return self.request("token/list",{"userId":user} if user else {})
    def tokenCreate(self,name,access=-1,objects=[],params={}):
        return self.request("token/update",{"callMode":"create","app":name,"at":0,"dur":0,"fl":access,"items":objects,"p":json.dumps(params)})
    def tokenDelete(self, token):
        return self.request("token/update",{"callMode":"delete","h":token})
    def update(self):
        with urlopen(self.base_url+"/avl_evts?sid=%s"%self.sid) as resp:
            data = json.loads(resp.read().decode("utf-8"))
            if "error" in data.keys() and data["error"]==1:#если истекла сессия то повторный логин и запрос
                return None
            else:
                return data

Не могу придумать как лучше обрабатывать ошибку 1. и сопутсвующие 1003 если попытаться перелогиниться немедленно.

2

error 1 и error 1003

Re: error 1 и error 1003

NeiroN пишет:

Как корректно обрабатывать ошибки связанные со входом  и истекшей сессией?

Из-за непонимания алгоритма получил вечную рекурсию.

Пока код такой

# -*- coding: utf-8 -*-
from urllib.request import Request,urlopen,install_opener,build_opener,ProxyHandler
from urllib.parse import urlencode
import json,os,time


class Tracker:
    base_url = "https://hst-api.wialon.com"
    sid = None
    api_key = None
    object_ids = None
    def __init__(self,api_key,name,sid=None):
        #install_opener(build_opener(ProxyHandler({"http": "http://proxy:3128","https":"https://proxy:3128"})))
        self.api_key = api_key
        self.name = name
        self.sid = sid or self.login(api_key,name).sid
    def request(self,svc,params):
        data = urlencode({"sid":self.sid,"svc":svc,"params":json.dumps(params)},safe=":/{},")
        headers = {"Content-Type": "application/x-www-form-urlencoded; charset=utf-8","Content-Length": len(data)}
        try:
            with urlopen(Request(self.base_url+"/wialon/ajax.html",bytes(data,"utf-8"),headers),timeout=2) as resp:
                data = resp.read()
                print(data)
                if isinstance(data,bytes):data = str(data,'utf-8')
                data = json.loads(data)
                if isinstance(data,dict) and "error" in data.keys():#если истекла сессия то повторный логин и запрос
                    if data["error"] == 1:
                        self.login()
                    if data["error"] == 1003:
                        print("Waiting for wialon ready")
                        time.sleep(60)
                    if self.sid:
                        return self.request(svc,params)
                    return None
                else:
                    return data
        except:
            print("Wialon timeout")
            return None
    def login(self,api_key=None,name=None):
        #print("WialonLogin():%s"%self.sid)
        self.sid = None
        data = self.request("token/login",{"token":api_key or self.api_key,"operateAs":name or self.name})
        if data:
            if "error" in data:
                return self
            self.name = data["user"]["nm"]
            self.sid = data["eid"]
            objects = None
            if "mongr" in data["user"]["prp"].keys():
                gobjects = json.loads(data["user"]["prp"]["mongr"])
                objects = []
                for k,v in gobjects.items():
                    objects += v
            if "monu" in data["user"]["prp"].keys() and not objects:
                objects = json.loads(data["user"]["prp"]["monu"])
            #self.object_ids = [int(x) for x in objects]
            #print(self.object_ids)
            #self.object_params = self.track(self.object_ids)
        return self
    def objects(self,ids=None):
        #print("WialonObjects():%s"%self.sid)
        data = self.request("core/search_items",{"spec":{"itemsType":"avl_unit","propName":"id","propValueMask":"*","sortType":"id"},"force":1,"flags":4194321,"from":0,"to":0})
        if data:
            data = data["items"]
        else:
            return None
        objects = {}
        for i,v in enumerate(data):
            v["uri"] = os.path.basename(v["uri"]).replace("svg","png")
            if ids:
                if v["id"] in ids:
                    objects[v["id"]] = v
            else:
                objects[v["id"]] = v
        return objects
    def track(self,objects):
        return {x["i"]:x["d"] for x in self.request("core/update_data_flags",{"spec":[{"type":"col","data":objects,"flags":4194304,"mode":1}]})}
    def tokenList(self,user=None):
        return self.request("token/list",{"userId":user} if user else {})
    def tokenCreate(self,name,access=-1,objects=[],params={}):
        return self.request("token/update",{"callMode":"create","app":name,"at":0,"dur":0,"fl":access,"items":objects,"p":json.dumps(params)})
    def tokenDelete(self, token):
        return self.request("token/update",{"callMode":"delete","h":token})
    def update(self):
        with urlopen(self.base_url+"/avl_evts?sid=%s"%self.sid) as resp:
            data = json.loads(resp.read().decode("utf-8"))
            if "error" in data.keys() and data["error"]==1:#если истекла сессия то повторный логин и запрос
                return None
            else:
                return data

Не могу придумать как лучше обрабатывать ошибку 1. и сопутсвующие 1003 если попытаться перелогиниться немедленно.

Для избежания рекурсии можно посмотреть в сторону retry декоратора

3

error 1 и error 1003

(13/05/2019 13:43:55 отредактировано NeiroN)

Re: error 1 и error 1003

retry декоратор это конечно хорошо, но вопрос больше в логике задержек и  что делать если сессия истекла(сколько не долбись но со старой сессией ответ не получить).

Задача класса получить валидные данные если есть связь.

И еще проблема что ИП адрес один а к мониторингу могут обращаться 10 пользователей в раз(разные sid) - как избежать 1003 если в раз выполняются 5...10 логинов с одинаковым api_key?
Допустим небыло инета, сессии истекли, появился инет - все разом ломанулись логиниться и получили 1003.