как создать команду curl из модуля запросов python?

Запросы Python — хороший модуль для облегчения программирования доступа к веб-REST API, я обычно делаю так, как показано ниже.

import json
url = 'https://api.github.com/some/endpoint'
payload = {'some': 'data'}
headers = {'Content-type': 'application/json', 'Accept': 'application/json'}

r = requests.post(url, data=json.dumps(payload), headers=headers)

И когда выходит ошибка, я хочу посмотреть, что за ней происходит. Создание команды curl для воспроизведения в командной строке является распространенным способом, поскольку это стандартный способ, наиболее подробно описанный в документе RESP API.

try:
    r = requests.post(url, data=json.dumps(payload), headers=headers)
except Exception as ex:
    print "try to use curl command below to reproduce"
    print curl_request(url,"POST",headers,payload)

Было бы неплохо, если бы я мог сгенерировать пример команды curl для этого запроса, см. хороший пример в отладке libcloud, я могу' Чтобы найти простой способ построения, ниже приведен метод, который я хочу создать самостоятельно.

# below code is just pseudo code, not correct 
def curl_request(url,method,headers,payloads):
    # construct curl sample from requests' structure
    # $ curl -v -H "Accept: application/json" -H "Content-type: application/json" 
    # -d '{"some":"data"}' 
    # -X POST https://api.github.com/some/endpoint
    request = "curl -v "
    for header in headers:
        print header
        request = request + '-H "' + header + ": " + headers[header] + '" '
    for payload in payloads:
        request = request + '-d {} "' + payload + ": " + payloads[payload] + '" '         
    request = request + "-X %s %s" % (method,url)
    return request

Также будет неплохо, если у нас уже есть метод в requests


Ниже приведено окончательное решение, получите ответ, работает для меня. Покажите это здесь для справки

def curl_request(url,method,headers,payloads):
    # construct the curl command from request
    command = "curl -v -H {headers} {data} -X {method} {uri}"
    data = "" 
    if payloads:
        payload_list = ['"{0}":"{1}"'.format(k,v) for k,v in payloads.items()]
        data = " -d '{" + ", ".join(payload_list) + "}'"
    header_list = ['"{0}: {1}"'.format(k, v) for k, v in headers.items()]
    header = " -H ".join(header_list)
    print command.format(method=method, headers=header, data=data, uri=url)    

person Larry Cai    schedule 30.07.2013    source источник


Ответы (2)


Этот метод когда-то существовал в запросах, но он далеко не имеет отношения к модулю. Вы можете создать функцию, которая принимает ответ и проверяет его атрибут request.

Атрибут request является объектом PreparedRequest, поэтому он имеет атрибуты headers и body. Тело — это то, что вы передаете curl с помощью -d, а заголовки могут быть сгенерированы, как вы делали выше. Наконец, вы захотите вытащить атрибут url из объекта request и отправить его. Перехватчики не имеют для вас значения, если только вы не делаете что-то с собственным обработчиком аутентификации.

req = response.request

command = "curl -X {method} -H {headers} -d '{data}' '{uri}'"
method = req.method
uri = req.url
data = req.body
headers = ['"{0}: {1}"'.format(k, v) for k, v in req.headers.items()]
headers = " -H ".join(headers)
return command.format(method=method, headers=headers, data=data, uri=uri)

Это должно работать. Ваши данные будут правильно отформатированы, будь то multipart/form-data или что-то еще.

person Ian Stapleton Cordasco    schedule 30.07.2013
comment
спасибо, это то, что я хочу сделать в примере кода, но это оказывается сложно, так как мне нужно обрабатывать разные типы данных, заголовки [заголовок] выше могут быть целыми числами, можете ли вы вставить свои примеры кодов, чтобы я мог сослаться ? - person Larry Cai; 30.07.2013
comment
Если вы передаете целые числа запросам и не получаете исключений, я не знаю, что вы делаете. Я могу поместить в свой ответ пример кода, и он будет работать с версиями Python, над которыми работают запросы (например, 2.6+). - person Ian Stapleton Cordasco; 30.07.2013
comment
Спасибо, ваши примеры кодов пока мне достаточно хороши, и я обновил вопрос кодами, которые использовал в реальности. - person Larry Cai; 30.07.2013
comment
То, что вы используете, вводит в заблуждение тех, кто не понимает, какую проблему вы решаете. Мне кажется, вы хотите кодировать JSON ВСЕ данные, с которыми имеете дело, когда на самом деле запрос вполне может быть закодирован другим способом. Если вы хотите, вы должны вместо этого добавить свой собственный ответ и указать на него с объяснением того, почему вы делаете то, что делаете. - person Ian Stapleton Cordasco; 30.07.2013
comment
Забавно, что вы используете GitHub API в качестве примера. Вы пробовали github3.py? - person Ian Stapleton Cordasco; 31.07.2013
comment
Я просто скопировал образец из веб-запросов, на самом деле я использую внутренний веб-сервис. Приятно видеть github3.py, возможно, я смогу попробовать, когда буду играть с github. - person Larry Cai; 31.07.2013
comment
команда не должна быть такой: 'curl -X {метод} -H {заголовки} -d {данные} {uri}' (обратите внимание, что я добавил и -d) - person nivcaner; 08.06.2014
comment
вместо "{headers}" мы должны заключать в кавычки каждый отдельный заголовок. Я отредактировал ответ, чтобы сделать это. - person Nickolay; 07.01.2017
comment
@Nickolay '"{0}: {1}"' добавит обратную косую черту \ к каждому " для экранирования, а команда curl в конечном итоге будет заполнена \, поэтому "'{0}: {1}'" не будет. - person Mike K; 11.08.2018
comment
Это не работает, если вы используете params для запроса. - person Robin Lavallée; 04.07.2020

Для этого вы также можете использовать curlify.

$ pip install curlify
...
import curlify
print(curlify.to_curl(r.request)) // r is the response object from the requests lib
person Daniel Gerber    schedule 20.06.2018
comment
Похоже, если произойдет что-то вроде тайм-аута, curlify не будет работать (поскольку нет объекта ответа) - есть предложения? - person cdm; 07.08.2019
comment
@cdm, вы можете использовать его в подготовленном запросе, который вы получаете из объекта запроса, вызывая метод prepare(). Вам нужно построить объект Request с помощью конструктора, а не одного из методов, который подготавливает запрос, а затем отправляет его. - person jonseymour; 02.06.2021