5

我正在尝试将大文件从 Google App Engine 的 Blobstore 保存到 Google Cloud Storage 以方便备份。

它适用于小文件(<10 mb),但对于较大的文件,它变得不稳定,GAE 抛出和 FileNotOpenedError。

我的代码:

PATH = '/gs/backupbucket/'
for df in DocumentFile.all():           
  fn = df.blob.filename
  br = blobstore.BlobReader(df.blob)
  write_path = files.gs.create(self.PATH+fn.encode('utf-8'), mime_type='application/zip',acl='project-private') 
  with files.open(write_path, 'a') as fp:
    while True:
      buf = br.read(100000)
      if buf=="": break
      fp.write(buf)
  files.finalize(write_path)

(在任务队列中运行以避免超过执行时间)。

引发 FileNotOpenedError:

回溯(最近一次通话最后):
  __call__ 中的文件“/base/python27_runtime/python27_lib/versions/third_party/webapp2-2.3/webapp2.py”,第 1511 行
    rv = self.handle_exception(请求,响应,e)
  __call__ 中的文件“/base/python27_runtime/python27_lib/versions/third_party/webapp2-2.3/webapp2.py”,第 1505 行
    rv = self.router.dispatch(请求,响应)
  文件“/base/python27_runtime/python27_lib/versions/third_party/webapp2-2.3/webapp2.py”,第 1253 行,在 default_dispatcher
    返回 route.handler_adapter(请求,响应)
  __call__ 中的文件“/base/python27_runtime/python27_lib/versions/third_party/webapp2-2.3/webapp2.py”,第 1077 行
    返回 handler.dispatch()
  文件“/base/python27_runtime/python27_lib/versions/third_party/webapp2-2.3/webapp2.py”,第 547 行,在调度中
    return self.handle_exception(e, self.app.debug)
  文件“/base/python27_runtime/python27_lib/versions/third_party/webapp2-2.3/webapp2.py”,第 545 行,在调度中
    返回方法(*args, **kwargs)
  文件“/base/data/home/apps/s~simplerepository/1.354754771592783168/processFiles.py”,第 249 行,在帖子中
    fp.write(buf)
  文件“/base/python27_runtime/python27_lib/versions/1/google/appengine/api/files/file.py”,第 281 行,在 __exit__
    自我关闭()
  文件“/base/python27_runtime/python27_lib/versions/1/google/appengine/api/files/file.py”,第 275 行,关闭
    self._make_rpc_call_with_retry('关闭',请求,响应)
  _make_rpc_call_with_retry 中的文件“/base/python27_runtime/python27_lib/versions/1/google/appengine/api/files/file.py”,第 388 行
    _make_call(方法、请求、响应)
  _make_call 中的文件“/base/python27_runtime/python27_lib/versions/1/google/appengine/api/files/file.py”,第 236 行
    _raise_app_error(e)
  _raise_app_error 中的文件“/base/python27_runtime/python27_lib/versions/1/google/appengine/api/files/file.py”,第 179 行
    引发 FileNotOpenedError()

我已经进一步调查,根据对GAE 问题 5371的评论,文件 API 每 30 秒关闭一次文件。我在其他任何地方都没有看到这个记录。

我试图通过关闭和打开文件来解决这个问题,但现在我得到了一个 WrongOpenModeError。下面的代码是从这篇文章的第一个版本编辑的,我在文件的关闭和打开之间添加了 0.5 秒的暂停。它现在抛出一个 WrongOpenModeError。

我的代码(更新):

PATH = '/gs/backupbucket/'
for df in DocumentFile.all():           
  fn = df.blob.filename
  br = blobstore.BlobReader(df.blob)
  write_path = files.gs.create(self.PATH+fn.encode('utf-8'), mime_type='application/zip',acl='project-private') 
  fp = files.open(write_path, 'a')
  c = 0
  while True:       
    if (c == 5):
      c = 0
      fp.close()
      files.finalize(write_path)
      time.sleep(0.5)
      fp = files.open(write_path, 'a')
    c = c + 1
    buf = br.read(100000)
    if buf=="": break
    fp.write(buf)
  files.finalize(write_path)

堆栈跟踪:

回溯(最近一次通话最后):
  __call__ 中的文件“/base/python27_runtime/python27_lib/versions/third_party/webapp2-2.3/webapp2.py”,第 1511 行
    rv = self.handle_exception(请求,响应,e)
  __call__ 中的文件“/base/python27_runtime/python27_lib/versions/third_party/webapp2-2.3/webapp2.py”,第 1505 行
    rv = self.router.dispatch(请求,响应)
  文件“/base/python27_runtime/python27_lib/versions/third_party/webapp2-2.3/webapp2.py”,第 1253 行,在 default_dispatcher
    返回 route.handler_adapter(请求,响应)
  __call__ 中的文件“/base/python27_runtime/python27_lib/versions/third_party/webapp2-2.3/webapp2.py”,第 1077 行
    返回 handler.dispatch()
  文件“/base/python27_runtime/python27_lib/versions/third_party/webapp2-2.3/webapp2.py”,第 547 行,在调度中
    return self.handle_exception(e, self.app.debug)
  文件“/base/python27_runtime/python27_lib/versions/third_party/webapp2-2.3/webapp2.py”,第 545 行,在调度中
    返回方法(*args, **kwargs)
  文件“/base/data/home/apps/s~simplerepository/1.354894420907462278/processFiles.py”,第 267 行,在获取
    fp.write(buf)
  文件“/base/python27_runtime/python27_lib/versions/1/google/appengine/api/files/file.py”,第 310 行,写入
    self._make_rpc_call_with_retry('追加',请求,响应)
  _make_rpc_call_with_retry 中的文件“/base/python27_runtime/python27_lib/versions/1/google/appengine/api/files/file.py”,第 388 行
    _make_call(方法、请求、响应)
  _make_call 中的文件“/base/python27_runtime/python27_lib/versions/1/google/appengine/api/files/file.py”,第 236 行
    _raise_app_error(e)
  _raise_app_error 中的文件“/base/python27_runtime/python27_lib/versions/1/google/appengine/api/files/file.py”,第 188 行
    引发 WrongOpenModeError()

我试图找到有关 WrongOpenModeError 的信息,但唯一提到的地方是 appengine.api.files.file.py 本身。

非常感谢有关如何解决此问题并能够将大文件保存到 Google Cloud 存储的建议。谢谢!

4

3 回答 3

3

IMO 你不应该files.finalize(write_path)间隔,finalize 使文件可读,你不能再把它改成可写。

于 2012-04-18T11:23:34.610 回答
1

我遇到了同样的问题,最终围绕获取数据编写了一个迭代器并捕获了异常,但它是一种解决方法。

重写您的代码将类似于:

from google.appengine.ext import blobstore
from google.appengine.api import files

def iter_blobstore(blob, fetch_size=524288):
  start_index = 0
  end_index = fetch_size

  while True:
    read = blobstore.fetch_data(blob, start_index, end_index)

    if read == "":
      break

    start_index += fetch_size
    end_index += fetch_size

    yield read


PATH = '/gs/backupbucket/'
for df in DocumentFile.all():           
  fn = df.blob.filename
  br = blobstore.BlobReader(df.blob)
  write_path = files.gs.create(self.PATH+fn.encode('utf-8'), mime_type='application/zip',acl='project-private') 
  with files.open(write_path, 'a') as fp:
    for buf in iter_blobstore(df.blob):
      try:
        fp.write(buf)
      except files.FileNotOpenedError:
        pass
  files.finalize(write_path)
于 2012-10-06T15:48:42.253 回答
-1

后端是您可以选择的选项吗?这将在后台运行,并且比 TaskQueue 具有更大的功能。

于 2011-11-23T21:52:13.630 回答