wow-dkp-engine笔记:数据库中文编码问题及其他

先前我需要处理的问题是生成一个类似这个连接的表格,由于这个表格的各项数据是直接从数据库提取数据计算出来然后在提交给Google Visualization API,最后返还结果。这样做最大的弊端是如果数据比较多的情况下会引发一个datastore timeout: operation took too long的异常,于是我重写了这个程序把计算的结果变成一个数据库,这样做就避免了引发这个异常的问题。

使用正则表达式匹配中英文字符

这个问题也困扰了我很长时间。我需要从类似:


MiDKPData = {};
MiDKPData["dkp"] = {};


MiDKPData["dkp"][1] = {};
MiDKPData["dkp"][1]["name"] = "开心圈圈DKP";
MiDKPData["dkp"][1]["members"] = {};
MiDKPData["dkp"][1]["members"]["Donesee"] = 5;
MiDKPData["dkp"][1]["members"]["Latrogue"] = 0;
MiDKPData["dkp"][1]["members"]["Longwalker"] = 15;
MiDKPData["dkp"][1]["members"]["Lovelace"] = 56;
MiDKPData["dkp"][1]["members"]["Lucid"] = 232;
MiDKPData["dkp"][1]["members"]["Mitnick"] = 0;
MiDKPData["dkp"][1]["members"]["Neverlose"] = 33;
MiDKPData["dkp"][1]["members"]["Ooxxoo"] = 10;
MiDKPData["dkp"][1]["members"]["Shadowghost"] = 3;
MiDKPData["dkp"][1]["members"]["Steafinie"] = 14;
MiDKPData["dkp"][1]["members"]["一脸猥琐"] = 5;
MiDKPData["dkp"][1]["members"]["三聚氰胺"] = 31;
MiDKPData["dkp"][1]["members"]["人生真谛"] = 20;
MiDKPData["dkp"][1]["members"]["伟大的乌瑟尔"] = 5;
MiDKPData["dkp"][1]["members"]["光之留香"] = 73;

这样的数据中提取字符,这应该是Lua中数据类型。开始我考虑用处理字符串的方法提取,但经过测试效率很低而且容易出错。然后我尝试使用正则表达式匹配这些数据,使用正则表达式匹配的话需要对里面可能出现的中文进行匹配,该文件正常情况下应该是采用UTF-8编码。

def retext(data):
    data = data.split('\n')
    dict0 = {}
    for li in data:
        m = re.match(r"(\[\")(\w+|[\x80-\xff]+|[\u3400-\u9FFF]+)(\"\]\s\=\s)(\d+)(\;)",li)
        try:
            dict0[m.group(3)]=m.group(5)
        except AttributeError:
            pass
    return dict0

retext()中的[\x80-\xff]+可以匹配任意长度的UTF-8编码的中文,而[\u3400-\u9FFF]+可以匹配任意长度的unicode编码中文。我在函数中加入了对unicode编码进行匹配的原因是我需要处理的这个字符串是通过request.POST.get()发送到服务器的。而这个request.POST.get()正是使用unicode编码。如果在数据库中查询这些数据则还需要使用decode('utf-8')将字符转化成UTF-8编码。

数据对象key_name属性

设置数据库字段的key_name属性:如果某些字符串和数据库的对象是一一对应的,而这些字符串刚好又符合设置成key_name的条件,那么把这些字符串设置成key_name属性会方便许多

Google Code开始支持Mercurial

我也是在前段时间python开始使用Mercurial才开始关注这个版本控制系统,很多我们所熟悉的程序包括:

等都采用Mercurial进行版本控制。

  • 支持向https://projectname.googlecode.com/hg发送pushing和pulling
  • 支持email commit
  • 支持浏览源码
  • 支持独立的changesets和diffs
  • 可视化的changeset DAG
  • 支持post-commit code reviews

Google Code的Mercurial支持目前还在测试当中,可以通过填写申请获得测试资格。

Google App Engine SDK Version 1.2.1更新

GAE中使用Google Visualization API

Google Visualization API看上去是个蛮不错的东西,在GAE环境中可以通过移植数据源的方式访问GAE中的数据,以便生成动态的图形。Google visualization python(gviz_api)是可以实现Python中数据类型转换成Visualization API可以使用的json格式的代码,而在django中则可以简单的通过将json数据写入模板来实现。比如:

google.load("visualization", "1", {packages:["table"]});

google.setOnLoadCallback(drawTable);
function drawTable() {
    var json_data = new google.visualization.DataTable({{ json }}, 0.5);
    var json_table = new google.visualization.Table(document.getElementById('table_div_json'));
    json_table.draw(json_data, {allowHtml: true, showRowNumber: true});}		

这个{{ json }}就是通过gviz_api中的ToJSon方法生成的json格式数据。其实就像这个我用数据生成的饼型图利用Google Chart也可以生成图片格式的图形,速度要比Visualization API快得多,这一点让我很难在这个wow-dkp-engine程序中取舍。

后来在使用Visualization API生成这张表格的时候遇到一个数据库的异常:

Timeout: datastore timeout: operation took too long

可能由于数据库运算时间过长,导致GAE服务器得不到数据库的响应。这个问题暂时还不太好解决,可能需要用把这个表格数据都放入缓存,然后让gviz_api去缓存中提取数据。大概也可以通过分页来解决这个问题。暂时先用捕捉异常的方法让程序得以运行,一旦发生异常则停止所有操作,只显示异常发生之前计算好的数据,所以每次访问返还的结果居然还都是不一样的...

使用多选框和HttpRequest提交数据

我记得google.appengine.ext.db的djangoforms里面的确是有个类叫做ModelMultipleChoiceField,但是现在已经没有了,不过ModelChoiceField还在。我目前的问题是想建立由模型生成的表单,通过checkbox提交这个模型中被选择的数据,如果checked那么将所有数据提交到一个模型的ListPropery属性形成一个key的列表,否则的话就不提交。

if request.method == 'POST':
   choosed_players_key = []
   post_players = request.POST.getlist('player')
   choosed_players = models.Players.get(post_players)
   for player in choosed_players:
      choosed_players_key.append(player.key())
      players_list.players = choosed_players_key
   players_list.put()
players_list是一个包含ListProperty的模型的实例,它的这个属性是由db.Key构成的,但是当我直接让:
players_list.players = request.POST.getlist('player')

的时候却发生了错误,players_list.players这个db.Key竟然是Key.from_path()生成的列表,所以后来改成先通过request.POST.getlist('player')获得所有player对象,然后在通过对象获得对象的key,再把这些key形成列表,最后再把这个列表赋值给players_list的players属性,这样竟然就可以了。

参考:附录H HTTP请求(Request)和回应(Response)对象

Google App Engine SDK Version 1.2.0发布

  • Cron支持。Appcfg.py将会上传在App Engine中执行的计划任务。开发环境的后台/_ah/admin对设置的计划任务进行描述但并不会执行,更多内容参考cron
  • 新的allow_skipped_files标记可以使开发服务器读取App Engine中不可用的文件。
  • appcfg提供新的upload_data命令行来运行bulk uploader,更多内容

Google发布Google App Engine SDK for Java

Google App Engine SDK for Java果然如约而至,看来在Issues list长期排名第一的feature Request果然起到了一些作用。GAE的Java运行环境为Java6JVM,支持JDO(Java Data Objects)、JPA(Java Persistence API),JavaMail,JCache。此外Google还提供Google Plugin for Eclipse使用Eclipse和Google Web Toolkit开发App Engine for Java项目。

Java运行环境

App Engine使用Java6的虚拟机。App Engine SDK支持Java5和更早的版本,Java6虚拟机能够运行任意版本Java编译出的程序。

App Engine使用Java Servlet作为Web应用程序。你可以在程序目录中提供你的servlet类,JaveServer Pages(JSPs),静态文件和数据文件,web.xml和其他配置文件。App Engine的服务器请求通过根据web.xml创建的servlets启动。

JVM使用'sandbox'的运行环境来独立你的程序。"sandbox"能够确保你的程序仅能够执行而不影响其他程序性能和扩展性。比如,一个程序不能超越线程,将文件写入本地系统或者建立网络连接。一个程序只能使用JNI或者其他的代码。JVM能够执行任何在"sandbox"允许运行的java代码。更多内容参考Servlet运行环境

数据库、服务和标准接口

App Engine提供可扩展的服务,程序可以存储数据、通过网络访问资源,和执行其他任务比如操作图片数据。程序访问Java的服务可以通过建立Java提供的各种APIs来进行。每个服务都可以通过提供一个完整的low-level接口来移植新或者直接访问。 App Engine Datastore访问用到的Java Data Objects (JDO) 2.3和Java Persistence API (JPA) 1.0似乎都使用DataNucleus Access Platform这个工具进行了移植。

对App Engine Memcache进行操作的工具是JCache (JSR 107).对于URL Fetch功能App Engine for Java采用java.net.URLConnection和java标准库中一些相关的类来实现。App Engine for Java使用JavaMail来发送email信息。图片服务使程序能够转换和操作图片数据,包括裁剪、转动、缩放和颜色变化。这一服务能够处理CPU-intensive Image处理任务,而节省服务器可用资源来处理web请求。程序可以使用Google Accounts来进行用户验证。Google Accouts处理用户帐户创建和登陆,已经注册的google用户可以使用帐户直接登录你的程序。Java程序可以使用在开发环境中使用安全限制来控制Google Account的访问,通过对servlet请对象使用getUserPrincipal()方法能够检测用户是否已经登陆。一个程序能够使用low-level Google Accounts API来生成登入和登出的URLs,并通过读取用户数据库中数据获得用户对象。

计划任务

程序能够通过设置一定的时间间隔来访问URLs的计划任务。更多内容查看Cron Jobs

Creative Commons 3.0 BY