2

クラウド ストレージ バケットから 5 つの基本的なテキスト ファイルを読み取り、圧縮して、BlobStore に書き込もうとしています。

from google.appengine.api import files
from google.appengine.ext import blobstore
from google.appengine.ext.webapp import blobstore_handlers
import StringIO
import zipfile

class FactoryHandler(blobstore_handlers.BlobstoreDownloadHandler):
   def get(self):
       """ SERVE THE BLOB, IF KEY AVAILABLE """
       k = self.request.get('key')
       if k:
           self.send_blob(k)
           return

       """ TAKES FROM CLOUD STORAGE , ZIPS IT """
       zipstream = StringIO.StringIO()
       zfile = zipfile.ZipFile(file=zipstream, mode='w')
       objects = files.listdir('/gs/test-bucket')

       for o in objects:
           with files.open(o, 'r') as f:
               data = f.read(1)

               while data != "":
                   zfile.writestr(o.encode('utf-8'),data)
                   data = f.read(1)

       zfile.close()
       zipstream.seek()

       """ NOW, ADD ZIP TO BLOBSTORE """
       zip_file = files.blobstore.create(mime_type='application/zip',_blobinfo_uploaded_filename='test.zip')
       zip_data = zipstream.getvalue()
       with files.open(zip_file, 'a') as f:
           f.write(zip_data)

       files.finalize(zip_file)
       blob_key = files.blobstore.get_blob_key(zip_file)
       self.response.out.write(blob_key)

どういうわけか、私はいつも各テキスト ファイルの最後の文字だけになってしまいます。を呼び出しているためだと思いf.read(1)ますが、コードは基本的に各バイトを反復処理してから、zfileオブジェクトに書き込みます。

データを連結してみました:

for o in objects:
    with files.open(o, 'r') as f:
        data = f.read(1)

        while data != "":
            data += f.read(1)

        """ once completed, write """
        zfile.writestr(o.encode('utf-8'),data)

しかし、App Engine 開発サーバーがハングします。おそらく、データを連結できないためです。

解決策はありますか?これはテキスト以外のファイルでも機能しますか? (画像、mp3 など)

編集:

そのため、実稼働アプリ + Google ストレージ アカウントで回答を実行しました。

このエラーが発生しました

ApplicationError: 8 
Traceback (most recent call last):
File "/base/python_runtime/python_lib/versions/1/google/appengine/ext/webapp/_webapp25.py", line       
710, in __call__
handler.get(*groups)
File "/base/data/home/apps/s~app-name/v1-55-app- 
proto.363439297871242967/factory.py", line 98, in get
with files.open(o, 'r') as f:
File "/base/python_runtime/python_lib/versions/1/google/appengine/api/files/file.py", line 520, 
in open
exclusive_lock=exclusive_lock)
File "/base/python_runtime/python_lib/versions/1/google/appengine/api/files/file.py", line 276,  
in __init__
self._open()

File "/base/python_runtime/python_lib/versions/1/google/appengine/api/files/file.py", line 423,    
in _open
self._make_rpc_call_with_retry('Open', request, response)
File "/base/python_runtime/python_lib/versions/1/google/appengine/api/files/file.py", line 427,   
in _make_rpc_call_with_retry
_make_call(method, request, response)
File "/base/python_runtime/python_lib/versions/1/google/appengine/api/files/file.py", line 252, 
in _make_call
_raise_app_error(e)

File "/base/python_runtime/python_lib/versions/1/google/appengine/api/files/file.py", line 210,  
in _raise_app_error
raise PermissionDeniedError(e)

PermissionDeniedError: ApplicationError: 8 

私の ACL 設定は正しかった (以前に ACL Access Denied Error を取得して修正した)

元の設定に追加された ACL 設定、バケット固有

   <Entry>
        <Scope type="UserByEmail">
            <EmailAddress>
                app-name@appspot.gserviceaccount.com
            </EmailAddress>
        </Scope>
        <Permission>
            FULL_CONTROL
        </Permission>
    </Entry>

ヒントはありますか?https://developers.google.com/appengine/docs/python/googlestorage/exceptionsのドキュメントによると

exception PermissionDeniedError()
The application does not have permission to perform this operation.

更新 - ファイルを public_read に設定すると、アプリを介してファイルを読み取ることができることに気付きました。これは、私のアプリがプライベート モードでアクセスするように適切に構成されていないことを意味します。ヒントはありますか?(私が知っている)それを修正する唯一の方法はACLを使用することであり、私はすでにその部分を構成しています。

4

1 に答える 1

2

ベン0、

関数ZipFile.writestr()は、ファイル全体を zipfile に書き込みます。すべてのファイルのデータを読み取ってから、ファイルごとに 1 回 writestr() を呼び出す必要があります。

2 番目のコード ブロックは正しい軌道に乗っていますが、無限ループを回避するために while チェックを更新する必要があります。このコードでは「データ」が空になることはないため、最後に読み取られたチャンクを確認するには、小さな変更が必要です。このようなものが動作するはずです:

for o in objects:
    with files.open(o, 'r') as f:
        data_list = []

        chunk = f.read(1000)

        while chunk != "":
            data_list.append(chunk)
            chunk = f.read(1000)

        data = "".join(data_list)

        """ once completed, write """
        zfile.writestr(o.encode('utf-8'),data)

また、1 バイトより大きいチャンクを読み取ると少し速くなる可能性がありますが、小さなテキスト ファイルを使用しているため、それほど問題にはなりません。

于 2012-11-26T00:42:51.377 に答える