Google App Engine: "无法创建已存在的文件
我在Windows 7上运行Google App Engine的开发服务器1.3.3。
通常情况下,这个方法都能正常工作,但这次却出现了错误:
def _deleteType(type):
results = type.all().fetch(1000)
while results:
db.delete(results)
results = type.all().fetch(1000)
错误信息:
File "src\modelutils.py", line 38, in _deleteType
db.delete(results)
File "C:\Program Files\Google\google_appengine\google\appengine\ext\db\__init__.py", line 1302, in delete
datastore.Delete(keys, rpc=rpc)
File "C:\Program Files\Google\google_appengine\google\appengine\api\datastore.py", line 386, in Delete
'datastore_v3', 'Delete', req, datastore_pb.DeleteResponse(), rpc)
File "C:\Program Files\Google\google_appengine\google\appengine\api\datastore.py", line 186, in _MakeSyncCall
rpc.check_success()
File "C:\Program Files\Google\google_appengine\google\appengine\api\apiproxy_stub_map.py", line 474, in check_success
self.__rpc.CheckSuccess()
File "C:\Program Files\Google\google_appengine\google\appengine\api\apiproxy_rpc.py", line 149, in _WaitImpl
self.request, self.response)
File "C:\Program Files\Google\google_appengine\google\appengine\api\datastore_file_stub.py", line 667, in MakeSyncCall
response)
File "C:\Program Files\Google\google_appengine\google\appengine\api\apiproxy_stub.py", line 80, in MakeSyncCall
method(request, response)
File "C:\Program Files\Google\google_appengine\google\appengine\api\datastore_file_stub.py", line 775, in _Dynamic_Delete
self.__WriteDatastore()
File "C:\Program Files\Google\google_appengine\google\appengine\api\datastore_file_stub.py", line 610, in __WriteDatastore
self.__WritePickled(encoded, self.__datastore_file)
File "C:\Program Files\Google\google_appengine\google\appengine\api\datastore_file_stub.py", line 656, in __WritePickled
os.rename(tmpfile.name, filename)
WindowsError: [Error 183] Cannot create a file when that file already exists
我哪里做错了?为什么这次会失败,而之前都没问题呢?
更新 我重启了开发服务器,结果重新上线后,数据存储区是空的。
2 个回答
(声明:我不是在回答你的问题,而是在帮你优化你正在运行的代码)
你的代码似乎在大量删除对象。在SDK/开发服务器中,你可以使用这个命令更快更方便地清空数据存储:
$ dev_appserver.py -c helloworld
当然,这个命令是用来清空整个SDK数据存储的。如果你不想清空全部,那就别用这个命令。:-)
更重要的是,如果你把查询改成类似下面的形式,你的代码会运行得更快,并且在生产环境中使用更少的CPU:
results = type.all(keys_only=True).fetch(SIZE)
这个方法和你的代码效果一样,只是它只获取了键,因为你在删除数据时并不需要从数据存储中获取完整的实体。此外,你的代码目前设置了 SIZE=1000
,但你可以把这个值设得更大,特别是如果你知道系统中大概有多少实体的话……在1.3.1版本中,1000的结果限制已经取消了 http://bit.ly/ahoLQp
还有一个小建议……尽量不要把 type
用作变量名……这是Python中最重要的对象之一,也是内置/工厂函数。如果你这样做,代码可能会出现奇怪的行为——在你的情况下,因为你是在一个函数/方法内部,所以影响不大,但如果作为全局变量就不一定了。
希望这些对你有帮助!
很遗憾,我无法查看1.3.3版本的源代码来准确诊断你的问题,因为这个SDK没有1.3.3的发布标签,我也无法猜测1.3.3中使用的datastore_filestub.py
的具体版本。你能不能升级到当前版本1.3.5再试试?使用旧版本(尤其是2个以上版本的旧版)并不推荐,因为它们可能和谷歌服务器上实际可用的内容有些不同(而且可能存在在新版本中已经修复的bug)。总之……
在Windows上,如果目标文件已经存在,os.rename
就无法正常工作。不过我看到的版本都很小心地处理了可能出现的OSError
(WindowsError
是从它派生出来的),会先删除已存在的文件,然后再尝试重命名。所以我不太明白你的bug是怎么回事——如果你使用的SDK源代码有这样的处理方式,我觉得是有的。
另外,我建议你使用--use_sqlite
(可以查看Nick Johnson在他的博客上发布的相关内容 这里),来替代SDK数据存储中的文件存根——这样做似乎更合理!-)