Отправка XML-запроса

Я провел в общей сложности 30 минут в python lol, так что примите это во внимание, когда вы ответите lol:

Я пытаюсь отправить HTTP-запрос POST с телом и читаю ответ. Я использую Python 3.6.5 в Windows 10. Вот что у меня есть:

импортировать http.client импорт xml.dom.minidom

HOST = "www.mysite.com"
API_URL = "/service"

def do_request(xml_location):

request = open(xml_location, "r").read()

webservice = http.client.HTTPConnection(HOST)

webservice.request("POST", API_URL)

webservice.putheader("Host", HOST)
webservice.putheader("User-Agent", "Python Post")
webservice.putheader("Content-type", "text/xml; charset=\"UTF-8\"")
webservice.putheader("Content-length", "%d" % len(request))
webservice.endheaders()

webservice.send(request)

statuscode, statusmessage, header = webservice.getreply()

result = webservice.getfile().read()
resultxml = xml.dom.minidom.parseString(result)

print (statuscode, statusmessage, header)
print (resultxml.toprettyxml())

with open("output-%s" % xml_location, "w") as xmlfile:
    xmlfile.write(resultxml.toprettyxml())

do_request("test.xml")

test.xml содержит XML-запрос. При запуске выдает ошибку:

Traceback (most recent call last):
  File "C:\Users\xxx\Documents\test.py", line 33, in <module>
    do_request("test.xml")
  File "C:\Users\xxx\Documents\test.py", line 14, in do_request
    webservice.putheader("Host", HOST)
  File "C:\Users\xxx\AppData\Local\Programs\Python\Python36\lib\http\client.py", line 1201, in putheader
    raise CannotSendHeader()
http.client.CannotSendHeader

Есть ли причина, по которой вы используете http.client? Это довольно низкоуровневый модуль; Обычно проще использовать urllib.request, если вам нужно придерживаться stdlib, или сторонний модуль requests, если вы этого не делаете. (Фактически, это первое, что говорит http.client документы…)

abarnert 02.05.2018 00:23

@abarnert - понятия не имею ... как я уже сказал, у меня около 5 минут опыта работы на python :). На самом деле это для интеграции в AppDynamics, поэтому я не уверен, есть ли какие-то ограничения.

SledgeHammer 02.05.2018 00:30

Ну где вы нашли http.client и как им пользоваться? Если вы распространяете целый беспорядок из чужого устаревшего кода, который повсюду использует http.client, вы можете узнать, как его использовать, но в противном случае вы, вероятно, этого не сделаете.

abarnert 02.05.2018 00:33
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
3
823
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваша проблема в том, что вы перепутали методы request и putrequest. (Неудивительно, учитывая краткость и разреженность документации ... большинство модулей в Python задокументированы намного лучше, чем этот, поэтому не позволяйте этому беспокоиться о будущем.)

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

Так что вы можете исправить это в любом случае.


(1) Измените его, чтобы использовать putrequest. Я понимаю, что нигде в документации нет примера использования putrequest или putheader, но это выглядит так:

webservice.putrequest("POST", API_URL)

webservice.putheader("Host", HOST)
webservice.putheader("User-Agent", "Python Post")
webservice.putheader("Content-type", "text/xml; charset=\"UTF-8\"")
webservice.putheader("Content-length", "%d" % len(request))
webservice.endheaders()

webservice.send(request)

(2) Измените его, чтобы использовать request. Это то, что делают все примеры в документации; вам просто нужно создать диктатор заголовков, чтобы передать ему:

headers = {
    "Host": HOST,
    "User-Agent": "Python Post",
    "Content-type", "text/xml; charset=\"UTF-8\"",
    "Content-length", "%d" % len(request)
}
webservice.request("POST", API_URL, headers=headers, body=request)

(3) Прочтите это в верхней части документации:

This module defines classes which implement the client side of the HTTP and HTTPS protocols. It is normally not used directly — the module urllib.request uses it to handle URLs that use HTTP and HTTPS.

See also The Requests package is recommended for a higher-level HTTP client interface.

В большинстве реальных случаев вы хотите использовать requests, если вы можете использовать стороннюю библиотеку, и urllib.request, если вы не можете. Они оба проще и лучше документированы.

У меня он работает с urllib. Библиотека запросов не работала, и я не хотел больше с ней связываться, лол :).

SledgeHammer 02.05.2018 00:45

Дополнительная благодарность :): По связанному с этим вопросу, как вы рекомендуете прочитать один или два узла из строки ответа xml с помощью xpath?

SledgeHammer 02.05.2018 00:47

@SledgeHammer lxml.etree обычно является лучшим выбором для простых XML-файлов или etree, если вы не можете использовать сторонние библиотеки. Ни один из них не имеет достаточно полной поддержки XPath (а stdlib немного более неполный, чем lxml), но их обоих обычно достаточно для того, что вы хотите, и с ними намного проще начать работу, чем с другими вариантами.

abarnert 02.05.2018 00:50

@SledgeHammer Другой популярный вариант - это BeautifulSoup, сторонняя библиотека, которая может обернуть lxml в еще более дружелюбный API, который может последовательно использоваться для HTML и XML и может обрабатывать различные виды небрежного поиска. Но если вы действительно знаете, какие запросы XPath хотите выполнять, вам, вероятно, лучше напрямую использовать lxml.

abarnert 02.05.2018 00:51

Хорошо, спасибо, я проверю etree. Мне не нужны сложные xpath, просто простые вещи ... это просто для того, чтобы убедиться, что ответ был успешным. Спасибо за указатели!

SledgeHammer 02.05.2018 00:56

Другие вопросы по теме