<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 11.8.?處理壓縮數據 你要支持的最后一個重要的 HTTP 特性是壓縮。許多 web 服務具有發送壓縮數據的能力,這可以將網絡線路上傳輸的大量數據消減 60% 以上。這尤其適用于 XML web 服務,因為 XML 數據 的壓縮率可以很高。 服務器不會為你發送壓縮數據,除非你告訴服務器你可以處理壓縮數據。 ## 例?11.14.?告訴服務器你想獲得壓縮數據 ``` >>> import urllib2, httplib >>> httplib.HTTPConnection.debuglevel = 1 >>> request = urllib2.Request('http://diveintomark.org/xml/atom.xml') >>> request.add_header('Accept-encoding', 'gzip') >>> opener = urllib2.build_opener() >>> f = opener.open(request) connect: (diveintomark.org, 80) send: ' GET /xml/atom.xml HTTP/1.0 Host: diveintomark.org User-agent: Python-urllib/2.1 Accept-encoding: gzip ' reply: 'HTTP/1.1 200 OK\r\n' header: Date: Thu, 15 Apr 2004 22:24:39 GMT header: Server: Apache/2.0.49 (Debian GNU/Linux) header: Last-Modified: Thu, 15 Apr 2004 19:45:21 GMT header: ETag: "e842a-3e53-55d97640" header: Accept-Ranges: bytes header: Vary: Accept-Encoding header: Content-Encoding: gzip header: Content-Length: 6289 header: Connection: close header: Content-Type: application/atom+xml ``` | | | | --- | --- | | \[1\] | 這是關鍵:一創建了 `Request` 對象,就添加一個 `Accept-encoding` 頭信息告訴服務器你能接受 gzip 壓縮數據。`gzip` 是你使用的壓縮算法的名稱。理論上你可以使用其它的壓縮算法,但是 `gzip` 是 web 服務器上使用率高達 99% 的一種。 | | \[2\] | 這是你的頭信息傳越網絡線路的過程。 | | \[3\] | 這是服務器的返回信息:`Content-Encoding: gzip` 頭信息意味著你要回得的數據已經被 gzip 壓縮了。 | | \[4\] | `Content-Length` 頭信息是已壓縮數據的長度,并非解壓縮數據的長度。一會兒你會看到,實際的解壓縮數據長度為 15955,因此 gzip 壓縮節省了 60% 以上的網絡帶寬! | ## 例?11.15.?解壓縮數據 ``` >>> compresseddata = f.read() >>> len(compresseddata) 6289 >>> import StringIO >>> compressedstream = StringIO.StringIO(compresseddata) >>> import gzip >>> gzipper = gzip.GzipFile(fileobj=compressedstream) >>> data = gzipper.read() >>> print data <?xml version="1.0" encoding="iso-8859-1"?> <feed version="0.3" xmlns="http://purl.org/atom/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="en"> <title mode="escaped">dive into mark</title> <link rel="alternate" type="text/html" href="http://diveintomark.org/"/> <-- rest of feed omitted for brevity --> >>> len(data) 15955 ``` | | | | --- | --- | | \[1\] | 繼續上面的例子,`f` 是一個從 URL 開啟器返回的類文件對象。使用它的 `read()` 方法將正常地獲得非壓縮數據,但是因為這個數據已經被 gzip 壓縮過,所以這只是獲得你想要的最終數據的第一步。 | | \[2\] | 好吧,只是先得有點兒凌亂的步驟。Python 有一個 `gzip` 模塊,它能讀取 (當然也能寫入) 磁盤上的 gzip 壓縮文件。但是磁盤上還沒有文件,只在內存里有一個 gzip 壓縮緩沖區,并且你不想僅僅為了解壓縮而寫出一個臨時文件。那么怎么做來從內存數據 (`compresseddata`) 創建類文件對象呢?這需要使用 `StringIO` 模塊。你首次看到 `StringIO` 模塊是在[上一章](../scripts_and_streams/index.html#kgp.openanything.stringio.example "例?10.4.?StringIO 介紹"),但現在你會發現它的另一種用法。 | | \[3\] | 現在你可以創建 `GzipFile` 的一個實例,并且告訴它其中的 “文件” 是一個類文件對象 `compressedstream`。 | | \[4\] | 這是做所有工作的一行:從 `GzipFile` 中 “讀取” 將會解壓縮數據。感到奇妙嗎?是的,它確實解壓縮了數據。`gzipper` 是一個類文件對象,它代表一個 gzip 壓縮文件。盡管這個 “文件” 并非一個磁盤上的真實文件;但 `gzipper` 還是從你用 `StringIO` 包裝了壓縮數據的類文件對象中 “讀取” 數據,而它僅僅是內存中的變量 `compresseddata`。壓縮的數據來自哪呢?最初你從遠程 HTTP 服務器下載它,通過從用 `urllib2.build_opener` 創建的類文件對象中 “讀取”。令人吃驚吧,這就是所有的步驟。鏈條上的每一步都完全不知道上一步在造假。 | | \[5\] | 看看吧,實際的數據 (實際為 15955 bytes)。 | “等等!” 我聽見你在叫。“還能更簡單嗎!” 我知道你在想什么。你在,既然 `opener.open` 返回一個類文件對象,那么為什么不拋棄中間件 `StringIO` 而通過 `f` 直接訪問 `GzipFile` 呢?OK,或許你沒想到,但是別為此擔心,因為那樣無法工作。 ## 例?11.16.?從服務器直接解壓縮數據 ``` >>> f = opener.open(request) >>> f.headers.get('Content-Encoding') 'gzip' >>> data = gzip.GzipFile(fileobj=f).read() Traceback (most recent call last): File "<stdin>", line 1, in ? File "c:\python23\lib\gzip.py", line 217, in read self._read(readsize) File "c:\python23\lib\gzip.py", line 252, in _read pos = self.fileobj.tell() # Save current position AttributeError: addinfourl instance has no attribute 'tell' ``` | | | | --- | --- | | \[1\] | 繼續前面的例子,你已經有一個設置了 `Accept-encoding: gzip` 頭信息的 `Request` 對象。 | | \[2\] | 簡單地打開請求將獲得你的頭信息 (雖然還沒下載任何數據)。正如你從 `Content-Encoding` 頭信息所看到的,這個數據被要求用 gzip 壓縮發送。 | | \[3\] | 從 `opener.open` 返回了一個類文件對象,從頭信息中你可以獲知,你將獲得 gzip 壓縮數據。為什么不簡單地通過那個類文件對象直接訪問 `GzipFile` 呢?當你從 `GzipFile` 實例 “讀取” 時,它將從遠程 HTTP 服務器 “讀取” 被壓縮的數據并且立即解壓縮。這是個好主意,但是不行。由 gzip 壓縮的工作方式所致,`GzipFile` 需要存儲其位置并在壓縮文件上往返游走。當 “文件” 是來自遠程服務器的字節流時無法工作;你能用它做的所有工作就是一次返回一個字節流,而不是在字節流上往返。所以使用 `StringIO` 這種看上去不太優雅的手段是最好的解決方案:下載壓縮的數據,用 `StringIO` 創建一個類文件對象,并從中解壓縮數據。 |
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看