Nano Hash - криптовалюты, майнинг, программирование

Завернуть запрос POST в код pycurl

Я пытаюсь преобразовать следующий запрос curl в pycurl:

curl -v
-H Accept:application/json \
-H Content-Type:application/json \
-d "{
    name: 'abc',
    path: 'def',
    target: [ 'ghi' ]
}" \
-X POST http://some-url

У меня есть следующий код Python:

import pycurl, json

c = pycurl.Curl()
c.setopt(pycurl.URL, 'http://some-url')
c.setopt(pycurl.HTTPHEADER, ['Accept: application/json'])
data = json.dumps({"name": "abc", "path": "def", "target": "ghi"})
c.setopt(pycurl.POST, 1)
c.setopt(pycurl.POSTFIELDS, data)
c.setopt(pycurl.VERBOSE, 1)
c.perform()
print curl_agent.getinfo(pycurl.RESPONSE_CODE)
c.close()

При выполнении этого у меня возникла ошибка 415: неподдерживаемый тип носителя, поэтому я изменил:

c.setopt(pycurl.HTTPHEADER, ['Accept: application/json'])

в:

c.setopt(pycurl.HTTPHEADER, [ 'Content-Type: application/json' , 'Accept: application/json'])

На этот раз у меня 400: Плохой запрос. Но код bash с завитком работает. У вас есть идеи, что я должен исправить в коде Python?

05.08.2015

Ответы:


1

В вашем примере bash свойство target является массивом, в вашем примере Python это строка.

Попробуй это:

data = json.dumps({"name": "abc", "path": "def", "target": ["ghi"]})

Я также настоятельно рекомендую вам ознакомиться с библиотекой requests, в которой API гораздо лучше:

import requests
data = {"name": "abc", "path": "def", "target": ["ghi"]}
response = requests.post('http://some-url', json=data)
print response.status_code
05.08.2015
  • Библиотека запросов сломана во многих отношениях, чтобы быть бесполезной для любого строгого или слегка несоответствующего сервера. Есть запросы, которые отлично работают с curl, но которые отклоняются при выполнении с библиотекой запросов из-за ее различных ненужных очисток. 06.08.2016
  • @Nimrod спасибо за ваш комментарий. Я не знал об этом, и у меня никогда не было проблем с запросами, но мне было бы интересно узнать больше о проблемах, которые вы описываете. Можете ли вы указать мне любую дополнительную информацию? 07.08.2016
  • Нет, я категорически не согласен, запросы python не всегда являются чемпионом. Если вы хотите загрузить файл в читаемом потоке, на помощь приходит FORM_FILE pycurl. 17.10.2019

  • 2

    PycURL — это оболочка библиотеки libcurl, написанная на языке C, поэтому ее Python API может немного озадачить. Поскольку некоторые люди выступают за использование запросов Python, я просто хочу указать, что это не идеальная замена. Для меня отсутствие тайм-аута разрешения DNS было нарушителем условий сделки. Я также нахожу его намного медленнее на моем Raspberry Pi. Это сравнение может быть уместным: Python Requests vs PyCurl Performance

    Итак, вот что не ускользает от вопроса ОП:

    import pycurl
    import json
    from cStringIO import StringIO
    
    curl = pycurl.Curl()
    curl.setopt(pycurl.URL, 'http://some-url')
    curl.setopt(pycurl.HTTPHEADER, ['Accept: application/json',
                                    'Content-Type: application/json'])
    curl.setopt(pycurl.POST, 1)
    
    # If you want to set a total timeout, say, 3 seconds
    curl.setopt(pycurl.TIMEOUT_MS, 3000)
    
    ## depending on whether you want to print details on stdout, uncomment either
    # curl.setopt(pycurl.VERBOSE, 1) # to print entire request flow
    ## or
    # curl.setopt(pycurl.WRITEFUNCTION, lambda x: None) # to keep stdout clean
    
    # preparing body the way pycurl.READDATA wants it
    # NOTE: you may reuse curl object setup at this point
    #  if sending POST repeatedly to the url. It will reuse
    #  the connection.
    body_as_dict = {"name": "abc", "path": "def", "target": "ghi"}
    body_as_json_string = json.dumps(body_as_dict) # dict to json
    body_as_file_object = StringIO(body_as_json_string)
    
    # prepare and send. See also: pycurl.READFUNCTION to pass function instead
    curl.setopt(pycurl.READDATA, body_as_file_object) 
    curl.setopt(pycurl.POSTFIELDSIZE, len(body_as_json_string))
    curl.perform()
    
    # you may want to check HTTP response code, e.g.
    status_code = curl.getinfo(pycurl.RESPONSE_CODE)
    if status_code != 200:
        print "Aww Snap :( Server returned HTTP status code {}".format(status_code)
    
    # don't forget to release connection when finished
    curl.close()
    

    Есть еще несколько интересных функций, которые стоит проверить в документации libcurl curleasy setopts.

    06.12.2019
  • Модули StringIO и cStringIO исчезли. Вместо этого импортируйте модуль io и используйте io.StringIO или io.BytesIO для текста и данных соответственно. 24.12.2019
  • Может пригодится :from io import StringIO 24.12.2019
  • @MaxBase Интересно, но у cStringIO есть свое место, поскольку он написан на C, в отличие от io.StringIO или StringIO.StringIO, и можно увидеть, насколько хорошо он работает в этот тест Обычно PycURL, написанный на C, используется для написания более производительного кода, поэтому я думаю, что читатели сочтут cStringIO лучшим дополнением. 26.12.2019
  • Большое спасибо, это очень помогло мне после нескольких дней расследования 23.05.2020

  • 3

    Я знаю, что этому уже больше года, но, пожалуйста, попробуйте удалить пробел в значении заголовка.

    c.setopt(pycurl.HTTPHEADER, ['Accept:application/json'])
    

    Я также предпочитаю использовать модуль запросов, потому что API/методы понятны и просты в использовании.

    05.01.2017

    4

    У меня была аналогичная проблема, и я использовал ваш пример кода, но обновил раздел httpheader следующим образом:

    c.setopt(pycurl.HTTPHEADER, ['Content-Type:application/json'])
    
    04.01.2019

    5

    Лучше просто использовать библиотеку запросов. (http://docs.python-requests.org/en/latest)

    Я добавляю код Python для ваших оригинальных пользовательских заголовков curl.

    import json
    import requests
    
    url = 'http://some-url'
    headers = {'Content-Type': "application/json; charset=xxxe", 'Accept': "application/json"}
    data = {"name": "abc", "path": "def", "target":  ["ghi"]}
    res = requests.post(url, json=data, headers=headers)
    print (res.status_code)
    print (res.raise_for_status())
    
    05.01.2017
  • Пожалуйста, объясните, почему это лучше 05.01.2017
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..