2014-07-10 17 views
11

Tôi đang sử dụng Yêu cầu để tải xuống tệp (vài gigabyte) từ máy chủ. Để cung cấp thông tin cập nhật tiến bộ (và để ngăn chặn toàn bộ tập tin từ phải được lưu trữ trong bộ nhớ) tôi đã thiết stream=True và viết khi tải về vào một tệp:Tránh ChunkedEncodingError cho một đoạn trống với Yêu cầu 2.3.0

with open('output', 'w') as f: 
    response = requests.get(url, stream=True) 

    if not response.ok: 
     print 'There was an error' 
     exit() 

    for block in response.iter_content(1024 * 100): 
     f.write(block) 
     completed_bytes += len(block) 
     write_progress(completed_bytes, total_bytes) 

Tuy nhiên, tại một số điểm ngẫu nhiên trong việc tải xuống, yêu cầu ném ChunkedEncodingError. Tôi đã đi vào nguồn và thấy rằng this corresponds to an IncompleteRead exception. Tôi chèn một tuyên bố đăng nhập xung quanh những dòng đó và thấy rằng e.partial = "\r". Tôi biết rằng máy chủ cho phép tải xuống mức độ ưu tiên thấp và tôi nghi ngờ rằng ngoại lệ này xảy ra khi máy chủ đợi quá lâu để gửi đoạn tiếp theo.

Như dự kiến, ngoại lệ sẽ ngừng tải xuống. Thật không may, máy chủ không thực hiện các phạm vi nội dung của HTTP/1.1, vì vậy tôi không thể đơn giản tiếp tục nó. Tôi đã chơi xung quanh với tăng thời gian chờ nội bộ của urllib3, nhưng ngoại lệ vẫn còn tồn tại.

Có anyway để làm cho urllib3 cơ bản (hoặc yêu cầu) khoan dung hơn của các khối trống (hoặc muộn) để các tập tin hoàn toàn có thể tải về?

+0

Bạn đang sử dụng nền tảng nào? Tôi có thể đề nghị sử dụng một công cụ có thể chuyên dùng cho bạn mà bạn có thể gọi qua vỏ, chẳng hạn như curl không? –

+0

bạn có thể thử đặt thời gian chờ lâu hơn trong khi nhận (thời gian chờ kwarg sẽ hoạt động với luồng = True trong 2.3, xem https://github.com/kennethreitz/requests/issues/1803). Tôi cũng sẽ xác minh rằng tiêu đề của bạn cho loại nội dung và mã hóa khớp với những gì bạn đang mong đợi để đảm bảo rằng nó không cắt bớt luồng –

+0

Bạn đã thử với một khối nhỏ hơn? Có vẻ như tôi đã luôn sử dụng 1024 hoặc 2048. – Wyrmwood

Trả lời

1
import httplib 

def patch_http_response_read(func): 
    def inner(*args): 
     try: 
      return func(*args) 
     except httplib.IncompleteRead, e: 
      return e.partial 
    return inner 

httplib.HTTPResponse.read = patch_http_response_read(httplib.HTTPResponse.read) 

Tôi không thể tạo lại sự cố của bạn ngay bây giờ, nhưng tôi nghĩ đây có thể là bản vá. Nó cho phép bạn xử lý các máy chủ http bị lỗi.

Hầu hết các máy chủ xấu truyền tất cả dữ liệu, nhưng do lỗi triển khai, chúng đóng sai phiên và httplib tăng lỗi và chôn các byte quý giá của bạn.

Các vấn đề liên quan