Выполнение POST-вызова вместо GET с использованием urllib2 - PullRequest
52 голосов
/ 14 июня 2011

Существует много вещей, связанных с вызовами urllib2 и POST, но я застрял в проблеме.

Я пытаюсь сделать простой вызов POST для службы:

url = 'http://myserver/post_service'
data = urllib.urlencode({'name' : 'joe',
                         'age'  : '10'})
content = urllib2.urlopen(url=url, data=data).read()
print content

Я вижу журналы сервера, и он говорит, что я выполняю вызовы GET, когда отправляю аргумент данных в urlopen.

Библиотека выдает ошибку 404 (не найдена),что правильно для вызова GET, вызовы POST обрабатываются хорошо (я также пытаюсь использовать POST в форме HTML).

Ответы [ 7 ]

43 голосов
/ 14 июня 2011

На этот вопрос можно было ответить раньше: Python URLLib / URLLib2 POST .

Ваш сервер, вероятно, выполняет перенаправление 302 от http://myserver/post_service до http://myserver/post_service/. Когда выполняется перенаправление 302, запрос изменяется с POST на GET (см. Issue 1401 ). Попробуйте изменить url на http://myserver/post_service/.

43 голосов
/ 14 июня 2011

Делайте это поэтапно и модифицируйте объект следующим образом:

# make a string with the request type in it:
method = "POST"
# create a handler. you can specify different handlers here (file uploads etc)
# but we go for the default
handler = urllib2.HTTPHandler()
# create an openerdirector instance
opener = urllib2.build_opener(handler)
# build a request
data = urllib.urlencode(dictionary_of_POST_fields_or_None)
request = urllib2.Request(url, data=data)
# add any other information you want
request.add_header("Content-Type",'application/json')
# overload the get method function with a small anonymous function...
request.get_method = lambda: method
# try it; don't forget to catch the result
try:
    connection = opener.open(request)
except urllib2.HTTPError,e:
    connection = e

# check. Substitute with appropriate HTTP code.
if connection.code == 200:
    data = connection.read()
else:
    # handle the error case. connection.read() will still contain data
    # if any was returned, but it probably won't be of any use

Этот способ позволяет вам также выполнять запросы PUT, DELETE, HEAD и OPTIONS, просто подставляя значение метода или даже заключая его в функцию. В зависимости от того, что вы пытаетесь сделать, вам также может понадобиться другой обработчик HTTP, например для загрузки нескольких файлов.

12 голосов
/ 14 июня 2011

Модуль запросов может облегчить вашу боль.

url = 'http://myserver/post_service'
data = dict(name='joe', age='10')

r = requests.post(url, data=data, allow_redirects=True)
print r.content
10 голосов
/ 14 июня 2011

Прочитайте Руководство по отсутствию urllib .Из него извлечен следующий простой пример POST-запроса.

url = 'http://myserver/post_service'
data = urllib.urlencode({'name' : 'joe', 'age'  : '10'})
req = urllib2.Request(url, data)
response = urllib2.urlopen(req)
print response.read()

Как предложено @Michael Kent, рассмотрим запросов , это здорово.РЕДАКТИРОВАТЬ: Это сказал, я не знаю, почему передача данных в urlopen () не приводит к запросу POST;Должно.Я подозреваю, что ваш сервер перенаправляет или неправильно работает.

5 голосов
/ 14 июня 2011

it должен отправлять POST, если вы предоставляете параметр данных (как вы делаете):

из документов: «HTTP-запрос будет POST вместо GET, если указан параметр data»

так что ... добавьте отладочную информацию, чтобы увидеть, что происходит со стороны клиента.

Вы можете изменить свой код и повторить попытку:

import urllib
import urllib2

url = 'http://myserver/post_service'
opener = urllib2.build_opener(urllib2.HTTPHandler(debuglevel=1))
data = urllib.urlencode({'name' : 'joe',
                         'age'  : '10'})
content = opener.open(url, data=data).read()
1 голос
/ 14 июня 2011

Попробуйте вместо этого:

url = 'http://myserver/post_service'
data = urllib.urlencode({'name' : 'joe',
                         'age'  : '10'})
req = urllib2.Request(url=url,data=data)
content = urllib2.urlopen(req).read()
print content
0 голосов
/ 16 апреля 2015
url="https://myserver/post_service"
data["name"] = "joe"
data["age"] = "20"
data_encoded = urllib2.urlencode(data)
print urllib2.urlopen(url + "?" + data_encoded).read()

Может быть, это может помочь

...