我最近有一个硬盘驱动器崩溃并丢失了我所有的源代码。是否可以提取/ check out 我已经上传到 Google App Engine 的代码(如最新版本)?
最佳答案
由于我只是费了很大力气才弄清楚如何做到这一点,我想我也可以将其作为答案包含在内,即使它不适用于您:
在继续之前,在你母亲的坟墓上发誓下次你会备份你的代码,或者更好的是,使用源代码控制。我的意思是:在我之后重复“ 下次我将使用源代码管理”。好的,完成后,让我们看看是否可以为您恢复您的代码......
如果您的应用程序是用 Java 编写的,恐怕您就不走运了——Java 应用程序的源代码甚至没有上传到 App Engine。
如果您的应用程序是用 Python 编写的,并且同时具有 remote_api和 deferred定义的处理程序,可以通过这两个 API 的交互来恢复您的源代码。基本技巧是这样的:
按顺序查看它们:
启动 remote_api_shell
只需从命令行键入以下内容:
remote_api_shell.py your_app_id
如果 shell 不在您的路径中,请在命令前面加上 App Engine SDK 目录的路径。
将源写入数据存储
在这里,我们将利用以下事实:您安装了延迟处理程序,您可以使用 remote_api 将任务排入延迟队列,并且您可以延迟 Python 内置函数“eval”的调用。
由于 'eval' 只执行一条语句,而不是任意的代码块,所以这有点棘手,因此我们需要将整个代码表述为一条语句。这里是:
expr = """
[type(
'CodeFile',
(__import__('google.appengine.ext.db').appengine.ext.db.Expando,),
{})(
name=dp+'/'+fn,
data=__import__('google.appengine.ext.db').appengine.ext.db.Text(
open(dp + '/' + fn).read()
)
).put()
for dp, dns, fns in __import__('os').walk('.')
for fn in fns]
"""
from google.appengine.ext.deferred import defer
defer(eval, expr)
相当的黑客。让我们一次看一下:
首先,我们使用'type'内置函数动态创建db.Expando的新子类。 .
type()
的三个参数是新类的名称、父类的列表和类变量的字典。整个表达式的前 4 行等价于:from google.appengine.ext import db
class CodeFile(db.Expando): pass
' 的使用进口 ' 这是我们不能使用语句这一事实的另一种解决方法:表达式
__import__('google.appengine.ext.db')
导入引用的模块,并返回顶级模块 (google)。自
type()
返回新类,我们现在有一个可用于将数据存储到数据存储区的 Expando 子类。接下来,我们调用它的构造函数,向它传递两个参数,“name”和“data”。我们从当前正在处理的目录和文件的串联中构造的名称,而数据是打开该文件名并读取其内容的结果,包装在 db.Text 对象中,因此它可以是任意长的。最后,我们对返回的实例调用 .put() 以将其存储到数据存储区。为了读取和存储所有源文件,而不是一个文件,整个表达式发生在列表推导式中,该推导式首先迭代 os.walk 的结果。 ,它可以方便地返回基本目录下的所有目录和文件,然后覆盖每个目录中的每个文件。该表达式的返回值 - 写入数据存储的键列表 - 被延迟模块简单地丢弃。不过,这并不重要,因为这只是我们关心的副作用。
最后,我们调用 defer 函数,延迟对 eval 的调用,并将我们刚刚描述的表达式作为其参数。
读出数据
执行上述操作后,等待它完成,我们可以再次使用 remote_api 从数据存储中提取数据。首先,我们需要一个本地版本的代码文件模型:
import os
from google.appengine.ext import db
class CodeFile(db.Model):
name = db.StringProperty(required=True)
data = db.TextProperty(required=True)
现在,我们可以获取它的所有实体,并将它们存储到磁盘:
for cf in CodeFile.all():
os.makedirs(os.dirname(cf.name))
fh = open(cf.name, "w")
fh.write(cf.data)
fh.close()
就是这样!您的本地文件系统现在应该包含您的源代码。
一个警告:下载的代码将只包含您的代码和数据文件。静态文件不包括在内,但您应该能够简单地通过 HTTP 下载它们,如果您还记得它们都是什么的话。配置文件(例如 app.yaml)同样不包含在内,并且无法恢复 - 您需要重写它们。仍然比重写整个应用程序要好得多,对吧?
关于google-app-engine - 我可以恢复已上传到 Google AppEngine 的源代码吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2479087/