Форум программистов, компьютерный форум, киберфорум
Наши страницы
Python
Войти
Регистрация
Восстановить пароль
 
ElenaTomsk
4 / 4 / 0
Регистрация: 11.10.2014
Сообщений: 99
1

Ищу правильный путь по работе с web-api

26.04.2018, 18:57. Просмотров 359. Ответов 14
Метки нет (Все метки)

Здравствуйте !

Есть вот такой код:
Python
1
2
3
4
5
6
7
8
9
10
ticker_res = requests.get('https://wex.nz/api/3/ticker/[B]btc_usd[/B]')
ticker_res_obj = json.loads(ticker_res.text)
for pair in ticker_res_obj:
        btc_usd = ticker_res_obj[pair]['buy'] 
и подобных вызовов пять штук разных с разным значением, которые я выделила жирным   
 
ticker_res = requests.get('https://othersite.nz/[B]eth_usd[/B]')
ticker_res_obj = json.loads(ticker_res.text)
for pair in ticker_res_obj:
     eth_usd = ticker_res_obj[pair]['buy']
и подобных вызовов 15 штук разных с разным значением, которые я выделила жирным

В итоге получаю необходимое количество переменных с числовыми значениями внутри и подставляю их в запрос sql. Это дурость
и это надо оптимизировать.

Пока приходит в голову процедура, в которую буду передавать необходимую строку: "https://wex.nz/api/3/ticker/" or "https://othersite.nz/" and enumeration с [btc_usd, eth_usd] и возвращать перечисление же, а уже из него значения подставлять в строку. Работать будет, но как-то это некрасиво. Есть ли какой-то другой, красивый путь?

И сам запрос тоже немного смущает.
SQL
1
2
3
4
5
6
SELECT 1,
       {0} -- btc       
       UNION ALL 
SELECT 2,
       {1} --eth
        UNION ALL
Пока я сделала его строкой, куда подставляю значения из переменных через .format. Работает, но возможно, его надо генерить самой, тем более он однотипный? Или я зря переживаю и пытаюсь переоптимизировать код? Хотелось бы почитать про красивые практики.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
26.04.2018, 18:57
Ответы с готовыми решениями:

2 сервиса (WCF Web API и ASP.NET Web API) на одном хосте
Есть БД с юзерами Есть консольное приложение (OWIN selfhost) с контроллером...

Не правильный путь
Ребят привет) помогите разобраться с путями не пойму есть сайт index.php +...

Не правильный путь к файлу
Не запускается ни одно приложение, кроме браузера, переустановка не помогает, в...

Не правильный путь к файлу
Неправильный путь приложения: D:\GAmeS\World_of_Tanks\WorldOfTanks.exe ...

Не правильный путь файла
nable to start the game. Make sure the target and start point folder on the...

14
Welemir1
Автоматизируй это!
840 / 571 / 232
Регистрация: 30.03.2015
Сообщений: 2,197
26.04.2018, 19:09 2
Цитата Сообщение от ElenaTomsk Посмотреть сообщение
и это надо оптимизировать.
согласен. у респонза библиотеки requests разве нет уже встроенного метода json? зачем парсишь его текст?

код однотипный, вынеси в функцию, которой будешь передавать только то что у тебя выделено жирным и получать назад значения для переменной. В итоге циклом можно будет все запросы сделать. урлы можно константами сделать в функции и при обращении указывать каким-нить флагом true/false

это если я верно понял что у тебя в модуле 20 раз повторяется один и тот же код
0
ElenaTomsk
4 / 4 / 0
Регистрация: 11.10.2014
Сообщений: 99
26.04.2018, 19:14  [ТС] 3
Да, все верно понято. Как раз подобное решение я сама придумала, но что-то оно не нравится. Не похоже на "путь настоящего самурая", структурно, не объектно.
0
Welemir1
Автоматизируй это!
840 / 571 / 232
Регистрация: 30.03.2015
Сообщений: 2,197
26.04.2018, 19:18 4
ElenaTomsk, структурно - это как сейчас) Не, ну можно класс создать, который будет похожим поведением обладать, но оно тут нужно? Тем и силен Питон, что можно функциями, можно процедурно, можно в ООП стиле.
0
ElenaTomsk
4 / 4 / 0
Регистрация: 11.10.2014
Сообщений: 99
27.04.2018, 04:05  [ТС] 5
" у респонза библиотеки requests разве нет уже встроенного метода json? зачем парсишь его текст?"

Есть, но в чем особо выгода?
Вот сейчас получилось так:

Python
1
2
3
4
ticker_res = requests.get('https://wex.nz/api/3/ticker/btc_usd')
ticker_res = ticker_res.json()
for pair in ticker_res:
         btc_usd = ticker_res[pair]['buy']
Особой экономии не вижу, разве что на import json? Насчет того, что структурно именно сейчас - это я и писала. Но вроде правильный путь все через объекты?
Как раз и интересуюсь верными практиками.
0
Welemir1
Автоматизируй это!
840 / 571 / 232
Регистрация: 30.03.2015
Сообщений: 2,197
27.04.2018, 08:29 6
Цитата Сообщение от ElenaTomsk Посмотреть сообщение
Особой экономии не вижу
экономия - не юзаешь еще одну библиотеку, особенно, поторяющую уже имеющийся функционал
Цитата Сообщение от ElenaTomsk Посмотреть сообщение
правильный путь все через объекты?
а в пайтон все является объектом, в том числе и функции
1
Рыжий Лис
Просто Лис
1187 / 511 / 343
Регистрация: 17.05.2012
Сообщений: 2,066
Записей в блоге: 8
27.04.2018, 10:34 7
По-хорошему бы создать класс.

Но начнём с функций:
Python
1
2
3
4
5
6
7
8
9
def get_value(url):
    for pair in requests.get(url).json():
         btc_usd = ticker_res[pair]['buy']
         #...
    return btc_usd
 
 
a1 = get_value('https://wex.nz/api/3/ticker/btc_usd')
a2 = get_value('https://othersite.nz/eth_usd')
Про sql: есть bindParam()
1
ElenaTomsk
4 / 4 / 0
Регистрация: 11.10.2014
Сообщений: 99
27.04.2018, 22:55  [ТС] 8
У меня вот такая функция получилась:

Передаю строку с {0} и подставляю в нее значения из списка, возвращаю список цен. Однако обработка ошибок недостаточная. Если requests.get возвращает строку, непригодную для парсинга json, то все падает и показывается вот такой exception: json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0) А как ее перехватить, если json в input мне посоветовали убрать? И еще не знаю, правильно ли проверяю, что хоть что-то передано в качестве входных параметров.


Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import requests     # work with http request 
import pyodbc       # work with database
import datetime     # work with during of execute program  
import configparser # work with config file 
import re           # work with regular ex
 
def price_get(string_value, list_value):
       """
       the function returns list for sql string 
       """
       # проверить переданные строки. Если пустые - на выход. 
       # получить значения в цикле. 
       # присвоить их 
       m_return = [] #пустой список
       if (string_value == '' or list_value == ''):
              return -1       
       # убрать из переданной строки валют все пробелы всех возможных типов, включая переносы строк и табуляцию         
       
       list_value= re.sub(r'\s+', '', list_value) 
       list_value=list_value.split(",") # и превратить в список        
              #
       try:
              for m_value in list_value:
                     ticker_res = string_value.format(m_value) # брать текущее значение и подставить в строку 
                     ticker_res = requests.get(ticker_res).json() # получить данные с текущей валютой
                     for pair in ticker_res:
                            m_return.append(ticker_res[pair]['buy']) # добавить в список текущее значение 
       except (requests.exceptions.RequestException):
                     m_return = -1
       return m_return # список цен возвратить вызывателю
0
Garry Galler
1439 / 1160 / 426
Регистрация: 28.10.2013
Сообщений: 2,947
27.04.2018, 23:39 9
Цитата Сообщение от ElenaTomsk Посмотреть сообщение
Если requests.get возвращает строку, непригодную для парсинга json, то все падает
Нужно проверять заголовки ответа - сервер всегда присылает Content-Type, который указывает на тип содержимого.
Вот элементарная проверка, что тип содержимого является json'ом.
Python
1
2
resp = requests.post('http://httpbin.org/get')
resp.headers['Content-Type'] == 'application/json'
После чего к полученному ответу можно безопасно применить
Python
1
resp.json()
Добавлено через 1 минуту
Цитата Сообщение от ElenaTomsk Посмотреть сообщение
обработка ошибок недостаточная
У вас ее вообще нет. Вы даже код ответа сервера не проверяете. Не говоря уж об ошибках коннекта....

Добавлено через 10 минут
P.S. Хотя нет, коннект проверяется. Но никакой полезной логики у вас там не прописано.
1
ElenaTomsk
4 / 4 / 0
Регистрация: 11.10.2014
Сообщений: 99
01.05.2018, 06:36  [ТС] 10
Проверка, конечно, вещь хорошая. Но сервера по-разному отдают эту строку.
Вот:
https://wex.nz/api/3/ticker/ltc_usd отдает, как я понимаю, честный json
А вот:
https://yobit.net/api/3/ticker/lcc_usd
отдает просто строку. И да, я пока очень плохо разбираюсь и в ответах сервера и в самом питоне. Если проверять вашим способом, то второй запрос всегда неверный.
0
vic5710
245 / 164 / 103
Регистрация: 10.12.2016
Сообщений: 549
01.05.2018, 10:20 11
Python
1
2
3
4
5
>>> d = requests.get('https://wex.nz/api/3/ticker/ltc_usd').json()
>>> d1 = requests.get('https://yobit.net/api/3/ticker/lcc_usd').json()
{'ltc_usd': {'high': 152.52064, 'low': 146.01, 'avg': 149.26532, 'vol': 3050195.29994, 'vol_cur': 20297.47747, 'last': 147.88159, 'buy': 148.316544, 'sell': 147.446636, 'updated': 1525158860}}
>>> d1
{'lcc_usd': {'high': 0.21999999, 'low': 0.19971865, 'avg': 0.20985932, 'vol': 8932.65081831, 'vol_cur': 42945.51772791, 'last': 0.19971865, 'buy': 0.19971865, 'sell': 0.20384916, 'updated': 1525158853}}
и то и то возвращает словарь
можете ошибки обрабатывать так
Python
1
2
3
4
5
try:
    #тут чего-то делаю
except Exception as e:
    print(e)
    #перехват всех исключений
1
Garry Galler
1439 / 1160 / 426
Регистрация: 28.10.2013
Сообщений: 2,947
01.05.2018, 13:38 12
Цитата Сообщение от ElenaTomsk Посмотреть сообщение
то второй запрос всегда неверный
Да, согласен: yobit привирает с типом содержимого ответа, говоря что отдает text/html; charset=utf8, отдает все-таки чистый json. Тогда как вам уже написали выше просто оберните вызов декодирования json в try catch и проверяйте на ошибки декодирования.

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>>> resp = requests.get('http://docs.python-requests.org/en/master/user/quickstart/')
>>> resp.json()
Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    resp.json()
  File "D:\INSTALL\Python3\lib\site-packages\requests\models.py", line 892, in json
    return complexjson.loads(self.text, **kwargs)
  File "D:\INSTALL\Python3\lib\site-packages\simplejson\__init__.py", line 518, in loads
    return _default_decoder.decode(s)
  File "D:\INSTALL\Python3\lib\site-packages\simplejson\decoder.py", line 370, in decode
    obj, end = self.raw_decode(s)
  File "D:\INSTALL\Python3\lib\site-packages\simplejson\decoder.py", line 400, in raw_decode
    return self.scan_once(s, idx=_w(s, idx).end())
simplejson.errors.JSONDecodeError: Expecting value: line 2 column 1 (char 1)
>>>
Добавлено через 10 минут
И не забывайте предварительно проверять, что
Python
1
resp.status_code == 200
И только потом делать все операции с получением содержимого.

Добавлено через 40 минут
P.S. Для перехвата ошибок декодирования json в requests необязательно перехватывать именно simplejson.errors.JSONDecodeError (здесь нужно предварительно еще импортировать simplejson.errors).
По документации requests достаточно использовать ValueError:

Python
1
2
3
4
5
6
7
>>> try:
    resp.json()
except ValueError as err:
    print(err)
 
    
Expecting value: line 2 column 1 (char 1)
1
ElenaTomsk
4 / 4 / 0
Регистрация: 11.10.2014
Сообщений: 99
03.05.2018, 13:16  [ТС] 13
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#coding:utf-8
import requests     # work with http request 
import pyodbc       # work with database
import datetime     # work with during of execute program  
import configparser # work with config file 
import re           # work with regular ex
 
def price_get(string_value, list_value):
       """
       the function returns list for sql string 
       проверить переданные строки. Если пустые - на выход. 
       получить значения в цикле. 
       присвоить их 
       
       коды возврата: 
       -10 - не передано значение
       -20 - какая-то беда стряслась с соединением
       -30 - запрос к серверу безответен в своих чувствах 
       -40 - ошибка при парсинге json 
       -50 - стряслась беда при чтении значений 
       -60 - значение цены меньше или равно нулю
       """
       m_return = [] #пустой список
       list_value= re.sub(r'\s+', '', list_value) # убрать из переданной строки валют все пробелы всех возможных типов, включая переносы строк и табуляцию         
       if (string_value == '' or list_value == ''): # проверить, что вообще хоть что-то передано 
              return -10 
      
       list_value=list_value.split(",") # и превратить в список. 
       try:
              for m_value in list_value:
                     ticker_res = string_value.format(m_value) # брать текущее значение и подставить в строку. url как строка с {0} и в него добавляется название пары, btc_usd, например.  
                     ticker_res = requests.get(ticker_res) 
                     # проверить, что ответ пришел 
                     if ticker_res.status_code != 200:
                            return -30 
                     try:                     
                           ticker_res = ticker_res.json() # парсить данные с текущей валютой
                           for pair in ticker_res:
                                 try:                           # проверяю, что существует такой параметр, buy
                                    if (ticker_res[pair]['buy'] > 0): # что значение больше нуля 
                                           m_return.append(ticker_res[pair]['buy']) # добавить в список текущее значение 
                                    else:
                                           return -60   # значение цены меньше-равно 0          
                                 except (KeyError):   
                                    return -50          # не найден параметр buy или еще какая беда с ключами     
                     except (ValueError): # какая-то ошибка при парсинге 
                            return -40 # 
       except (requests.exceptions.RequestException):
                     m_return = -20  # беда с соединением
       # число элементов в исходящем списке m_return равно числу элементов во входящем list_value? 
       
       return m_return # никаких ошибок не стряслось, список цен возвратить вызывателю
Вот так у меня получилось. Покритикуете? Меня точно смущает проверка параметров, так ли надо делать...
0
vic5710
245 / 164 / 103
Регистрация: 10.12.2016
Сообщений: 549
03.05.2018, 15:23 14
зачем так сложно?
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import requests
urls = [
    'https://wex.nz/api/3/ticker/ltc_usd',
    'https://yobit.net/api/3/ticker/lcc_usd_err',#неправильно
    ]
data = []
for i in urls:
    try:
        r = requests.get(i).json()
        data.append(r)
    except Exception as e:
        data.append(e)
 
for i in data:
    if 'error' in i.keys(): print('ERROR',i)
    else: print('OK',i)
Добавлено через 43 минуты
или так
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import requests
urls = [
    'https://wex.nz/api/3/ticker/ltc_usd',
    'https://ybit.net/api/3/ticker/lcc_usd',#неправильно
    ]
data = []
errlog = []
for url in urls:
    try:
        r = requests.get(url,timeout=3)
        if (r.status_code == 200):
            data.append(r.json())
    except Exception as e:
        errlog.append(url)
 
for i in data:
    if 'error' in i.keys(): print('JSON ERROR',i)
    else: print("OK",i)
 
for i in errlog: print('URL ERROR',i)
1
ElenaTomsk
4 / 4 / 0
Регистрация: 11.10.2014
Сообщений: 99
07.05.2018, 20:53  [ТС] 15
Ну, в вашем варианте нет нескольких проверок и вы продолжаете обработку, даже если произошла ошибка. Мне же надо останавливать выполнение, ну и хотелось бы точно отдавать вызывателю, что именно случилось. Конечно, спасибо в любом случае, но если в остальном мой код верный, на нем и остановлюсь.
0
07.05.2018, 20:53
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
07.05.2018, 20:53

Правильный путь до папки
День добрый! Имеется основной сайт и сайт-админка для него. При загрузке...

укажите правильный путь
добрый день уважаемые . имею процессор 4460 и задался таким вопросом: почему он...

Правильный путь к Program Files
Ребят, как правильно указать относительный путь к program files? и '%Program...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru