2012-12-05 4 views
2

여러 부분 양식 데이터를 서버로 보내는 RESTful API POST-verb에 대한 테스트를 작성하고 있습니다. 데이터를 json-encode하고 싶습니다. 그렇게하는 올바른 방법은 무엇입니까? 다음은 3 가지 테스트 중 첫 2 단계와 3 단계 (필요한 시나리오)가 실패하는 테스트입니다. 어떤 도움을 주시면 감사하겠습니다.파이썬 요청

import requests 
import json 

print "test 1, files+data/nojson" 
requests.post('http://localhost:8080', files={'spot[photo]': open('test.jpg', 'rb')}, data={'spot': 'spot_description'}) 

print "test 2, only data/json" 
requests.post('http://localhost:8080',data=json.dumps({'spot': 'spot_description'})) 

print "test 3, only files+data/json" 
requests.post('http://localhost:8080', files={'spot[photo]': open('test.jpg', 
'rb')}, data=json.dumps({'spot': 'spot_description'})) 

코드의 출력은 : 당신의 data 매개 변수가 문자열이기 때문에

$ /cygdrive/c/Python27/python.exe -B test.py 
test 1, files+data/nojson 
test 2, only data/json 
test 3, only files+data/json 
Traceback (most recent call last): 
    File "test.py", line 12, in <module> 
    'rb')}, data=json.dumps({'spot': 'spot_description'})) 
    File "C:\Python27\lib\site-packages\requests\api.py", line 98, in post 
    return request('post', url, data=data, **kwargs) 
    File "C:\Python27\lib\site-packages\requests\safe_mode.py", line 39, in wrapped 
    return function(method, url, **kwargs) 
    File "C:\Python27\lib\site-packages\requests\api.py", line 51, in request 
    return session.request(method=method, url=url, **kwargs) 
    File "C:\Python27\lib\site-packages\requests\sessions.py", line 241, in request 
    r.send(prefetch=prefetch) 
    File "C:\Python27\lib\site-packages\requests\models.py", line 532, in send 
    (body, content_type) = self._encode_files(self.files) 
    File "C:\Python27\lib\site-packages\requests\models.py", line 358, in _encode_files 
    fields = to_key_val_list(self.data) 
    File "C:\Python27\lib\site-packages\requests\utils.py", line 157, in to_key_val_list 
    raise ValueError('cannot encode objects that are not 2-tuples') 
ValueError: cannot encode objects that are not 2-tuples 
+0

테스트 할 시간이 없다는 사실은 open ('test.jpg', 'rb')'을 전달할 때 단순히 파일 IO 컨테이너를 전달한다는 것입니다. 실제 bytestream 인'open ('test.jpg', 'rb'). read()'를 전달해야합니다. – jdotjdot

+0

내일 확인하겠습니다. 파일을 전달하고 데이터의 일반 사전이 실제로 작동하기 때문에 이것은 올바르지 않습니다. –

답변

2

오류입니다. models.py::send()에서

:

# Multi-part file uploads. 
    if self.files: 
     (body, content_type) = self._encode_files(self.files) 

models.py::_encode_files()에서 :

fields = to_key_val_list(self.data) 
    files = to_key_val_list(files) 

utils.py::to_key_val_list()에서 :

if isinstance(value, (str, bytes, bool, int)): 
    raise ValueError('cannot encode objects that are not 2-tuples') 

이것은 self.data와 통화 타격을 받고있다. 과 같이, 자신을 당신은 사전의 캐릭터 라인 표현을 전달하고,하지만 사전을 기대하고 있어요 : 무엇이든은 파일 PARAM에 할당되어있는 경우

requests.post('http://localhost:8080', 
       files={'spot[photo]': open('test.jpg', 'rb')}, 
       data={'spot': 'spot_description'}) 

그래서, 다음 데이터 PARAM 유형의 캐릭터 라인이 될 수 없다, 바이트, bool 또는 int. 당신은 소스 코드에 따라 할 수 있습니다 JSON 데이터를 보내고 https://github.com/kennethreitz/requests/blob/master/requests/models.py#L531

+0

이것은 매우 합리적인 것처럼 들리지만 몇 가지 질문을 서 있습니다. 1. 왜 '파일'을 그대로두면 작동합니까? json에게 요청의 내용을 전달할 수 있습니다. –

+0

첫 번째 질문에 대한 답을 설명하기 위해 제 대답을 편집했습니다. 두 번째 질문에 대해서는 요청 모듈에서 가능한지 확실하지 않습니다. –

+0

노력에 감사드립니다. 귀하의 답변에 대해 찬성표를 던지 셨습니다. 동의하지 않으 셨습니다. 제가 갖고있는 주된 질문에 대해 더 나은 대답을 얻을 수 있기를 희망합니다. –

1

POST이 같은 형태로 인코딩 필드를 삽입하여 해결할 수 있습니다 또한

post(url, data={'data': json.dumps(actual_data)}, files={'myfile': open('foo.data')}) 

, 나는 그냥 넣을 수 있다고 생각 이 같은 files의 모든 :

post(url, files={'data': json.dumps(actual_data), 'myfile': open('foo.dat')}) 

... 첫 조각에 해당해야한다.