2016-10-13 3 views
4

저는 파이썬 requests 라이브러리를 사용하여 POST 요청을 보내고 있습니다. POST 데이터를 생성하는 프로그램 부분은 을 임의의 파일과 유사한 객체 (출력 스트림)에 쓸 수 있습니다.POST 데이터를 파이썬 요청으로 스트리밍하는 방법은 무엇입니까?

어떻게이 두 부분을 적합하게 만들 수 있습니까?

requests이이 사용 사례에 대해 스트리밍 인터페이스를 제공 할 것으로 예상했지만, 그렇지 않은 것으로 보입니다. 인 파일과 유사한 객체를 data 인수로 받아들입니다. 내가 할 수있는 파일과 같은 객체를 제공하지 않습니다. 을 작성하십시오.

이것은 파이썬 HTTP 라이브러리의 근본적인 문제입니까?

아이디어 지금까지이 :

가장 간단한 해결책은 fork()로하고 요청 라이브러리가 파이프 throgh POST 데이터 프로듀서와 통신 할 수 있도록하는 것 같다.

더 좋은 방법이 있습니까?

또는 POST 데이터 생성자를 복잡하게 만들 수 있습니다. 그러나 하나의 XML 스트림 (stdin)을 파싱하고 POST 데이터로 사용할 새 XML 스트림을 생성합니다. 그럼 난 반대의 동일한 문제가있다 : XML 시리얼 라이저 라이브러리 파일 형태의 객체에 쓰기, 나는 XML serializer가 파일 수있는 다른 객체를 제공 할 가능성을 전혀 모르고있다 .

또한 가장 깨끗하고 고전적인 해결책은 코 루틴 (coroutines)이며, 이는 파이썬에서 생성자 (yield)를 통해 다소 사용할 수 있음을 알고 있습니다. POST 데이터는 파일과 같은 객체가 아닌 (yield)을 통해 스트리밍되고 끌어 오기 구문 분석기를 사용할 수 있습니다.

그러나 requests에서 POST 데이터 반복자를 허용 할 수 있습니까? 그리고 yield과 함께 사용할 수있는 XML 시리얼 라이저가 있습니까?

또는 파일과 유사한 객체로 작성기를 작성하거나 반복자를 래핑하는 파일과 같은 객체를 제공하는 래퍼 객체가 있습니까?

+0

왜 제공 할 의무 _'requests'_한다 _ "파일 - 류 객체를 작성할 수있는 객체 "? _ 배경 모드가 아닌 전경에서 작동하도록 설계되었으므로 설명자를 제공하지 않고 수동으로 입력을 기다려야합니다. 필요한 경우, 'r, w = (os.fdopen (f, mode) for f, zip 모드 (os.pipe(), ("rb", "wb")와 같이 쉽게 제공 할 수 있습니다.))'- 그런 다음 두 부분을 별도의 스레드로 실행하십시오. –

답변

4

request은 반복자 또는 생성자를 data 인수로 사용하므로 자세한 내용은 Chunk-Encoded Requests에 설명되어 있습니다.데이터 크기가 미리 알려지지 않았기 때문에 전송 인코딩을이 경우 청크 처리해야합니다. 여기

queue.Queue를 사용하고 쓰기 위해 파일 - 류의 객체로 사용할 수있는 매우 simle 예입니다

import requests 
import queue 
import threading 

class WriteableQueue(queue.Queue): 

    def write(self, data): 
     # An empty string would be interpreted as EOF by the receiving server 
     if data: 
      self.put(data) 

    def __iter__(self): 
     return iter(self.get, None) 

    def close(self): 
     self.put(None) 

# quesize can be limited in case producing is faster then streaming 
q = WriteableQueue(100) 

def post_request(iterable): 
    r = requests.post("http://httpbin.org/post", data=iterable) 
    print(r.text) 

threading.Thread(target=post_request, args=(q,)).start() 

# pass the queue to the serializer that writes to it ...  
q.write(b'1...') 
q.write(b'2...') 

# closing ends the request 
q.close() 
+0

'if data :'가 정말로 필요하다고 생각하지 않습니다. 왜 빈 데이터가 "EOF로 해석 될 것인가?" iterator sentinel은 빈 바이트 스트링'b'''이 아니라'None'입니다. 따라서'q.write (b '')'는 EOF로 해석되지 않습니다. 그렇습니까? – vog

+1

@vog EOF로 해석하는 감시자가 아니므로 요청이 'b' '발생시 요청 스트리밍을 종료합니다. 그리고 외부 라이브러리 (예 : XML 직렬 변환기)를 사용하여이 파일과 같은 객체에 쓸 때 빈 문자열을 쓰지 않을지 확신 할 수 없습니다. 그것은 무언가'out.write (b ''. join (some_maybe_empty_list)) '를 무조건 할 것입니다. 빈 문자열을 쓰는 것은 파일을 "닫아서는 안됩니다"(실제로 닫히지는 않았지만 현재 반복자 만 종료합니다. "닫힌 상태"를 추가하는 것은 너무 어렵지 않을 것입니다) – mata

+0

오, 알아두면 좋을 것 같습니다. 이 문제를보다 명확하게 반영하도록 코드에서 주석을 조정했습니다. (뭔가 잘못 이해하면 의견을 고쳐 주셔도됩니다.) – vog

0

해당 데이터 싱크에 대한 푸시 인터페이스가 필요한 데이터 생성자와 해당 데이터 소스에 대한 풀 인터페이스가 필요한 데이터 소비자를 연결하는 유일한 방법은 중간 버퍼를 사용하는 것입니다. 그러한 시스템은 생산자와 소비자를 "병렬"로 운영함으로써 만 운영 될 수 있습니다 - 생산자가 완충액을 채우고 소비자가 완충액을 읽습니다. 완제품은 필요에 따라 중단됩니다. 이러한 병렬 처리는 cooperative multitasking으로 시뮬레이션 할 수 있습니다. 여기서 버퍼가 꽉 찼을 때 생산자가 소비자에게 제어권을 부여하고 소비자가 버퍼가 비게되면 소비자가 제어권을 생산자에게 반환합니다. 발전기 방식을 취함으로써 귀사의 사례를위한 맞춤형 협업 멀티 태스킹 솔루션을 구축하게 될 것입니다. 이는 생산자와 소비자의 일정을 관리하는 책임이 전적으로 사용자 중심의 작업 인 파이프 기반 접근 방식과 비교하면 더 간단합니다. OS.

관련 문제