2013-06-24 36 views
6

Tôi muốn tải xuống tệp qua giao thức HTTP sử dụng urllib3. tôi đã quản lý để làm sử dụng mã sau đây:Cách tốt nhất để tải xuống tệp bằng cách sử dụng urllib3

url = 'http://url_to_a_file' 
connection_pool = urllib3.PoolManager() 
resp = connection_pool.request('GET',url) 
f = open(filename, 'wb') 
f.write(resp.data) 
f.close() 
resp.release_conn() 

Nhưng tôi đã tự hỏi những thích cách để làm điều này là gì. Ví dụ: Nó sẽ hoạt động tốt cho các tệp lớn và Nếu không cần phải làm gì để làm cho mã này có khả năng chịu lỗi và có khả năng mở rộng cao hơn.

Lưu ý. Điều quan trọng là tôi phải sử dụng thư viện urllib3 không phải urllib2 ví dụ, vì tôi muốn mã của tôi là chuỗi an toàn.

Trả lời

14

Đoạn mã của bạn gần. Hai điều đáng chú ý:

  1. Nếu bạn đang sử dụng resp.data, nó sẽ tiêu thụ toàn bộ phản ứng và trả lại kết nối (bạn không cần phải resp.release_conn() thủ công). Điều này là tốt nếu bạn đang mát mẻ với việc giữ dữ liệu trong bộ nhớ.

  2. Bạn có thể sử dụng resp.read(amt) sẽ truyền phản hồi nhưng kết nối sẽ cần phải được trả lại qua resp.release_conn().

này sẽ giống như ...

import urllib3 
http = urllib3.PoolManager() 
r = http.request('GET', url, preload_content=False) 

with open(path, 'wb') as out: 
    while True: 
     data = r.read(chunk_size) 
     if not data: 
      break 
     out.write(data) 

r.release_conn() 

Các tài liệu có thể là một chút thiếu trên kịch bản này. Nếu bất cứ ai quan tâm đến việc thực hiện một pull-request to improve the urllib3 documentation, mà sẽ được đánh giá rất nhiều. :)

+0

Vâng. Cảm ơn về câu trả lời. –

+0

Và một câu hỏi nữa. Nó sẽ làm việc với phương thức POST nếu tôi thêm 'r = http.request ('POST', url)'? –

+0

@ running.t Err, đó là một sai lầm trong mã của tôi. Bạn nói đúng, phương pháp nên đi trước và đoạn mã của bạn sẽ hoạt động. (Cập nhật câu trả lời của tôi.) – shazow

-2

add tên biến preload_content khác mà bạn sẽ kết thúc tải toàn bộ nội dung

http.request('GET', url, preload_content=False) 
+0

@ 2Dee: Bạn có thể cho tôi biết điều gì sai ở đây vì vậy tôi có thể sửa bản thân mình – giridhar

+1

Tôi nghĩ rằng, trong khi câu trả lời của bạn có thể đúng (tôi không quen với urllib3), có vẻ như không giải quyết đầy đủ câu hỏi. Điều đó nói rằng, tôi đã không bỏ phiếu trả lời của bạn xuống, nếu bạn thấy tên của tôi xuất hiện dưới bài viết, đó là chỉ vì tôi đã chỉnh sửa câu trả lời của bạn để mã sẽ được định dạng đúng. Hy vọng điều này đã làm cho mọi thứ rõ ràng hơn cho bạn;) – 2Dee

2

Cách đúng nhất để làm điều này có lẽ là để có được một đối tượng tập tin giống như đại diện cho phản ứng HTTP và sao chép nó vào một tệp thực sự bằng cách sử dụng shutil.copyfileobj như sau:

url = 'http://url_to_a_file' 
c = urllib3.PoolManager() 

with c.request('GET',url, preload_content=False) as resp, open(filename, 'wb') as out_file: 
    shutil.copyfileobj(resp, out_file) 

resp.release_conn()  # not 100% sure this is required though 
Các vấn đề liên quan