python调用shell脚本的两种方法
python调用Shell脚本,有两种方法:os.system(cmd)或os.popen(cmd),前者返回值是脚本的退出状态码,后者的返回值是脚本执行过程中的输出内容。实际使用时视需求情况而选择。
现假定有一个shell脚本test.sh:
1 #!/bin/bash
2
3 echo "hello world!"
4 exit 3
os.system(cmd):
该方法在调用完shell脚本后,返回一个16位的二进制数,低位为杀死所调用脚本的信号号码,高位为脚本的退出状态码,即脚本中“exit 1”的代码执行后,os.system函数返回值的高位数则是1,如果低位数是0的情况下,则函数的返回值是0x100,换算为10进制得到256。
如果我们需要获得os.system的正确返回值,那使用位移运算可以还原返回值:
>>> n = os.system(test.sh)
>>> n >> 8
>>> 3
os.popen(cmd):
这种调用方式是通过管道的方式来实现,函数返回一个file-like的对象,里面的内容是脚本输出的内容(可简单理解为echo输出的内容)。使用os.popen调用test.sh的情况:
>>> file = os.popen(test.sh)
>>> file.read()
>>> 'hello world!\n'
明显地,像调用"ls"这样的shell命令,应该使用popen的方法来获得内容。
Pinax的意义
某天在研究pypy的时候无意中看到了pinax,了解之下,觉得pinax真的很聪明,跟我正打算做的事情很像!她是一个基于Django的基础应用--我这里讲基础应用的意思是她既不是开发框架,又不是一开箱即用的成熟应用(当然你不介意那简陋的界面的话,它是开箱即用的),而是介于两者之间的东西。她集成了很多第三方的Django app,这使得她自己内置了很多SNS网站、公司内部网站所需要的基础功能,你要做一个SNS网站,拿来改改界面就好,你要做公司内网应用,拿来改改界面也行了。
初次接触时,还没有安装来研究,就屁颠屁颠地跟老潘说这是个好东西(我对云和企业内部办公系统有些想法,经常和老潘交流),老潘一看说颇有Plone的影子了。后来安装下来看了看,离plone所谓的应用服务器那个级别还差远了,pinax可以看作是一系列的Project template(项目模板)。接下来给出几种模板的应用运行时的截图,大家看看就明白了。至于更深入的探究不是今天要说的,有兴趣的同学直接试一试更有意义。

图一:basic_project,最简单的应用模板。

图二:内部应用的模板,提供了几种内部应用用到的功能,如任务、wiki等。

图三:Pinax提供的最复杂的一个应用模板,SNS应用,不少SNS网站是基于这个来开发的。
Pinax给开发者带来什么?
一、没有技术上的转变,该用Django还是使用Django那套东西。
二、提供了一套基础网页模板和Tab布局。这个虽然简单,但十分实用,要换套皮肤,把现成的扔给美工MM略作修改即可,无需从0开始。
三、Pinax提供的最复杂的应用模板是一个SNS应用,实际上是一个完全可以马上投入使用的产品。Pinax说,我们已经为您提供所有需要的,你要做的只是让你的网站看起来与众不同。
题外话:
一、Django变得越来越强大的同时也变得复杂,要全部掌握Django的内容门槛不低,但这不妨碍初学者快速上手。
二、有人说,django变得越来越像zope,但实际上django的门槛恐怕没有zope的20%吧,虽然django渐渐肥胖,但新增的很多东西都是可选的,并且是在web开发过程中必需去解决的问题。大家看到新出一个web framework很清爽简单,不过走着瞧吧,到最后,他不是整合其他第三方的基础模块就是自己继续砌砖,直到又有ORM、Template、Form、中间件、UrlRoute、I18N,I10N等等等等,大家殊途同归,区别不过是OEM或Fullstack而已。
三、Django社区很活跃,看看第三方的app就知道,以至于有人可以全使用第三方的应用(没有自己的Model)搭起一个博客,以及现在这个pinax。
四、web应用开发领域,可重用的东西太多,于是有了框架,而技术之上的业务层面,可重用的东西也有很多,例如用户、权限、流程引擎等,Django首先把这业务层面可重用的东西做了一套参考标准并放到开发框架里面来了,大善!太实用了!这也是我几年前希望为公司内部的开发框架做的事(后来遇上Django后,没太多激情在java的webframework上折腾这些了)。
从Mac OS X 上移除 mysql
我这台机器上原来有Mysql,后来又用了MacPort,用Macport又装了个Mysql,搞到极其混乱,现在八不清谁跟谁,索性把他们都Uninstall了,然后再用Port重新装过。
先用Port把Port的版本unistall,前提是要停止Mysql:
sudo port uninstall mysql5
然后开始删文件吧。
sudo rm /usr/local/mysql
sudo rm -rf /usr/local/mysql*
sudo rm -rf /Library/StartupItems/MySQLCOM
sudo rm -rf /Library/PreferencePanes/My*
编辑 /etc/hostconfig 删除这行: MYSQLCOM=-YES- rm
-rf ~/Library/PreferencePanes/My*
sudo rm -rf /Library/Receipts/mysql*
sudo rm -rf /Library/Receipts/MySQL*
折腾TinyMCE图片上传的结果
由于敬爱的DropBox同学不幸被吾裆阉割了一半(不能访问外链,还能同步),导致本博的部分重要图片被墙,无法翻墙的同学看着大叉叉心神不宁。我以前使用毕卡索来做图片服务器,后来毕卡索被墙后换了DropBox,但不幸的是DB同学由于出过不少次风头而也被切了一半,看来,图片这东西还是放在自己服务器靠谱,就算被墙也是换个域名的事,不用大量修改文章里的图片链接那么痛苦。
本博在去年更新程序的时候换了TinyMCE做为WYSIWYG编辑器,但一直没有时间做个图片上传的插件(用不起官方那个商业版的),最近决定折腾折腾。
凡事先Google,django + tinymce + image 等关键字一出,马上找到一些好东东。
首先是Django-FileBrowser,她是一个强大而美丽的文件管理器。

更多截图。
然后我顺腾摸瓜找到了Django-grappelli,她又是一套优雅实用的Django-admin样式和扩展,除了有一套优雅大方的样式,她还为Admin加入了书签和导航栏等功能,甚为实用,可移步到这里来围观围观。
这两个应用都与TinyMCE完美整合,最好两者一起使用,当然不用grappelli也无大碍。
这两个应用我都照单全收了,我在线把她们安装到我的服务器上,这样一来,我不仅解决了图片上传的问题,还收获了一套美观的样式、得到了一个实用的文件管理器。喔!上艳照。

现在发图方便了,下面我要发飚了。
让R与Python共舞
R(又称R语言)是一款开源的跨平台的数值统计和数值图形化展现工具。通俗点说,R是用来做统计和画图的。R拥有自己的脚本语言和大量的统计、图形库(得益于开源社区),这让她看起来既美又实用。与其他同类软件(如SPSS)相比,R的特点是纯命令行的,这倒也好,我们更应该把注意力放在数据本身,而非统计工具的UI。
R虽说有一套自己的语言,还挺完备,但她最专业的还是做统计和画图,而像连接数据库、文本处理、文件操作等这些脏活可不能委屈R来干哪,这些得有其他语言来负责,我的选择是咱最熟悉的、做这些脏活最棒的Python。那接下来的问题很清楚了,R和Python如何一起工作?拍拍脑袋,想到可能有下面几种办法:
1. R和Python只共享文件,Python把源数据处理干净,生成格式化的文件放在预定的目录下,做个定时器让R去读文件,最终输出统计结果和图表。
这种做法一定程度上可行,除了做定时器外,还可以让Python即时执行"rscript"命令调用R脚本来工作,只是这种办法限制太大,只能够交换文件,Python不能对R进行精确的控制。
2. 让Python直接调用R的函数,R是开源项目,肯定会有一些第三方库实现Python与R互通。
果然,我找到了rpy2,可以实现使用python读取R的对象、调用R的方法以及Python与R数据结构转换等。实际上除了Python,其他语言与R互通的第三方包也大大的有。
最后我选择第2种方法,来让R与Python共舞。
模块 rpy2.robjects 是rpy2对R的一个高级封装,该模块里包含了一个r对象和一系列的R数据结构。使用rpy2的大多数情况,只需要跟这个模块打交道即可。rpy2的安装在此不多讲了,有兴趣的同学看文档去,直接体验一下R如何与Python无缝整合吧。
了解r实例
r实例是指rpy2.robjects.r,它是在Python中的嵌入式R进程,把r当作从python走向R的通道来看就可以了。通过r实例,我们可以读取R的内置变量、调用R的函数、甚至,直接把它当作R的解析器来用。
访问R的对象
在R的命令行中,我们直接输入对象名来访问R的内置对象,如pi、letters:
在R控制台中访问R对象
而使用r实例,python访问R对象也很简单,而且方法很多:
在python中访问R对象
在这段代码中,我们用了三种方式来访问R对象,把r实例当作字典,把r实例当作方法,把r实例当作一个类对象(真是神喻呀~)。在实际中,使用哪一种方式要因习惯而异,我喜欢的方法是使用第三种,把r实例当作自己人,直接使用"."来访问R对象。但这种方法有一个缺陷,就是不能访问带名字空间的R对象或函数,而其他两种方式是可以的,这点将在随后说明。
调用R函数
通过r实例,我们可以轻易地实现用Python调用R的函数。下面我们分别在R控制台和python命令行下读一个数据文件并画一张点图。
R控制台读取文件画点图
代码解读:
data.csv 的内容就是上面代码的3到7的内容。
data = read.table('data.csv') :把文件读进一个数据框变量data中。
mtx = data.matrix(data):把data转变成矩阵。
dotchart(mtx)用矩阵的数据画点图。
结果如下:
接下来用python来做一遍同样的事情,我们之前了解到,使用r实例可以直接访问R对象,还可以直接调用R的函数,其实在Python看来,对象和函数是相同的东西,函数也是一种对象罢了。现在来试一下调用"read.table()"函数读入一个数据文件data.csv:
出错了!怎么回事?在上面我提到过了,使用“.”引用的方式不能访问带有名字空间的R对象和函数,read.table 是表示在read包下面的table函数,通过"."的形式调用失败,必须要用字典的方式或参数的方式来获得:
这段代码得到的结果与在R控制台下画点图的效果是一样的。最后一行r.dotchart(mtx)是直接通过"."来调用R的函数dotchart的,在没有名实空间的情况下,是正常的。如果你为了避免太多不可控制的出错机会,你可以统一地使用字典的方式来访问R对象和方法,这是最保险的方法,虽然我个人认为看起来有点别扭。
r实例就是一R控制台
其实r实例就是一个可交互的R控制台,只不过交互对象是Python与R罢了,为了证明r实例具有R控制台的特性,来做个实验,写一串R脚本,作为Python一个字符串变量的内容,把该字符串传给r实例,然后把r实例当作方法来调用:

出来的结果这样:

注意,把r实例当作控制台,只能够通过r(r代码)的方式来使用r实例,字典的方式行不通。
加载自定义函数
在实际应用中,使用R语言来编写自己的函数同样是不可避免的,在R控制台中,可以使用source('script_path')的方法来加载自定义R脚本。而在Python中使用自己义R脚本中的函数也同样方便:使用r.source('script_path')即可把自定义函数加载到全局环境中,再使用r.自定义方法名就可以实现调用,我就是这样做的,在此不再详述,同学们自己动手玩一下。
R Vector与Python list
向量(Vector)是R的一个最重要的也是最常用的数据类型,可以理解为一个二维数据,对应Python的list。在R控制台中,声明一个变量:“x <- 1”,X会被声明成一个向量,而其第一个值是1。R常常用c()函数来声创建一个由多个值组成的向量,例如c(1,2,3,4)。Python要与R打交道,除了访问R对象和调用R函数,还有就是要学会如何转换常见的数据类型。
rpy2提供了几个类,供我们把Python的list转换成R的Vector。分别是robjects.IntVector,robjects.Boolvector,robjects.StringVector,robjects.FloatVector.以IntVector为例,将Python的list转换成R的Vector:robjects.IntVector([1,2,3,4,5]),毕!
下面来使用刚学到的类型转换知识画上一个例子的散点图来结束此次体验:
没有结束
rpy2提供的不仅仅是上面这些,上面的知识只是rpy2所提供的20%,但是已经足以解决80%的问题。rpy2还提供了更低级的API,你可以做更多的事情,例如你可以实现另一个robjects对象来支持使用"."来访问带名字空间的对象和函数。更多的知识,请移步官方文档。
ubuntu9.10下python访问Sql server的解决方案
在Linux/Unix/Mac下面通过程序来访问M$的Sql Server是一件很折腾的事情,赖总说,linux遇上windows就是杯具啊。最近不幸自己也遇上了,折腾了好一段时间,参考过不下于100+的网页,给过两个老外写邮件,终于还是没有搞定snow leopard上的,但总算搞定了linux上的。
纵观网上的一些参考材料,中文偏少,以赖总一年之前那篇被转载居多,而且大多数语焉不详,只道How,不道Why,当linux发行版本换或软件一升级就套不上了;英文很多,但各有千秋,参考起来也很头大。今天,咱在授人与鱼(如果你的系统配置和我的一样)之余顺便授人与渔,希望自己这次折腾的经验可以给以后需要的同学们带来点方便或启示什么的。
在开始之前,请问一下自己,真的有必要这样折腾吗?现在放弃还来得及,如果点头就继续往下看吧。
其实也没那么恐怖,我自己像个盲头苍蝇乱撞才会踫到一脸灰,如果一开始把原理搞清楚,做起来就快了。
首先,再确定一下我们的目标是:在linux下通过python访问Sql Server!关键字是linux、sqlserver、python。我的系统配置:ubuntu9.10 desktop 64bit、python2.5、SqlServer2005,配置不同的同学在理解原理之余应该也可以自行解决了。
基本原理
一、Linux下应用程序是一般怎样访问数据库的?
目前比较流行的方法是应用程序通过ODBC(Open DataBase Connectivity)来访问数据库。
在ODBC诞生之前,如果要开发数据库应用程序,则必须要使用数据库厂商随数据库产品一同发布的一些工具集来访问数据库,或者在程序中使用嵌入式SQL来访问数据库。当时,对于访问数据库的方法,缺乏一个基于C语言的统一编程接口。ODBC(Open Database Connectivity,开放数据库互连)提供了一种标准的API(应用程序编程接口)方法来访问DBMS(Database Management System)。这些API利用SQL来完成其大部分任务。

见ODBC的架构图,ODBC的驱动管理器自动处理各种数据库驱动与数据源(如各种数据库,甚至Excel)的关系,应用程序只需要使用ODBC的API即可,底层的细节对于应用程序来说是透明的。熟悉Java的同学回想一下JDBC,与ODBC的思路是一个道理,各种数据库有各自对应的JDBC驱动,同时也会有与之对应的ODBC驱动。
那么,要达到linux下应用程序访问数据库的目的,我们需要安装Linux下的ODBC库:unixODBC,目前ODBC在各种操作系统上均有实现,如windows的MS ODBC,还有Mac下的iODBC。
需要注意一点就是,要在Linux下让应用程序访问数据库,使用ODBC不是唯一的方法,只是本解决方案的方法。
二、怎样通过程序访问Sqlsever?
众所周知,程序访问数据库通常需要用到数据库的驱动程序(Database Driver)。Sqlserver(及SyBase)使用TDS(Tabular_Data_Stream)作为它的数据库现客户端传输的协议。关于TDS:
TDS(Tabular_Data_Stream)是一个应用层协议,用于数据库服务器与客户端传递数据,于1984年由Sybase公司发起并开发,用在它们的Sybase Sql Server关系数据库引擎,后来被微软的Sql Server所用。
所以不难理解,SqlServer的Java 驱动包 JTDS,就是TDS的一个Java实现(同时是JDBC的实现)。而For linux,开源社区有一个叫freetds的实现。Linux的程序可以直接通过它来访问SqlServer,是的,可以跳过ODBC。使用ODBC只不过是希望使得更多的方言(不同的编程语言)可以以一致的方式来访问数据库。
三、当Linux遇上SqlServer?
unixODBC使得linux上的程序可以以一统一的方式来访问数据源(这里叫以linux的方式),freetds是专为SqlServer而实现的数据库驱动。那么如果我们要以linux的方式去访问SqlServer呢?那就把两者两者连接起来吧!tdsodbc做这个的,在它的帮助下,linux上的应用程序完全可以不用关心freetds,只要以odbc的方式去访问数据源即可。
四、再加一个Python如何?
pyodbc是ODBC的一个python封装,它允许任何平台上的python具有使用ODBC API的能力。那意味着,pyodbc是python语言与ODBC的一条桥梁。
就这样,我们把它们的关系一拉直就是这样:
python程序 ─》pyodbc ─》ODBC(unixODBC) ─》Database Driver(freetds) ─》DataSource/Database。
开始行动
一、安装linux下Sqlserver的驱动程序
我们先来安装SqlServer的驱动程序,再安装ODBC相关的,目的是想尽快可以进行测试,因为在安装完Freetds之后,我们马上就可以在linux下连上SqlServer了。
安装Freetds,不要使用apt-get install 来安装,因为源里的版本不一定是新的,建议版本是0.82版,下载源码手工编译安装,因为有好些参数需要在编译中指定的。
1、使用命令行,切换到解压后freetds的目录下面,执行以下命令
./configure \
--prefix=/etc/freetds \
--with-tdsver=8.0
--enable-msdblib \
--enable-dbmfix \
--with-gnu-ld \
--enable-shared \
--enable-static
2、sudo make
3、sudo make install
好了。如果不出意外,freetds已经安装好了。再安装一个小工具freetds-bin,用来测试一下连接你的数据库:
apt-get freetds-bin
安装完毕后,可以使用tsql命令来进行测试SqlServer数据库连接:
jeff@ubuntu:~$ tsql -H 192.168.0.204 -p 1433 -U sa
locale is "en_US.UTF-8"
locale charset is "UTF-8"
Password:
1>
这时,成功地在Linux下访问上了远程的Sql Server数据库。胜利迈出了第一步!
二、安装linux下的ODBC驱动管理程序
现在安装unixODBC,让linux下的应用程序可以通过ODBC来访问数据源。我们需要分别安装unixodbc,unixodbc-dev,unixodbc-bin(可选),tdsodbc
apt-get install unixodbc unixodbc-dev unixodbc-bin tdsodbc
前面讲过了,ODBC驱动管理器会管理数据库驱动和数据源,那么它是如何管理的呢?答案是配置文件,分别有数据库驱动的配置文件和数据源的配置文件,分别是odbcinst.ini和odbc.ini,其所在的位置可能会因操作系统和安装方式而异,不过可以使用odbcinst -j命令来查看:
root@ubuntu:/home/jeff# odbcinst -j
unixODBC 2.2.11
DRIVERS............: /etc/odbcinst.ini
SYSTEM DATA SOURCES: /etc/odbc.ini
USER DATA SOURCES..: /root/.odbc.ini
在输出的结果中看到数据库驱动的配置文件是/etc/odbcinst.ini、数据源配置是/etc/odbc.ini和/root/odbc.ini。我们可以打开这两个文件看看,是没有内容D。现在我们要做的就是配置数据驱动以及数据源。
配置ODBC的时候,我们可以直接往两个配置里面增加内容,但这种方式不推荐,而推荐使用odbcinst命令来安装驱动信息和数据源信息。
配置数据驱动
首先,创建一个tds.driver.template的文件,输入以下内容并保存:
[TDS]
Description = FreeTDS Driver for Linux & MSSQL on Win32
Driver = /usr/lib/odbc/libtdsodbc.so
Setup = /usr/lib/odbc/libtdsS.so
[TDS]这一行意为开始定义一个名叫TDS的数据库驱动,下面是这个数据库的相关属性,请检查一下,Driver和Setup所指的两个lib文件是否存在,如果不存在,要好好检查一下这一步的安装工作有没到位啦,现在把tds.driver.template里定义的数据库驱动安装到系统的ODBC驱动库,执行如下命令:
root@ubuntu:/home/jeff# odbcinst -i -d -f tds.driver.template
-i 表示install,安装
-d 表示driver,所安装的是驱动
-f 表示file,指定要安装的文件
配置数据源
接下来,创建一个tds.datasource.template文件,输入以下内容并保存:
[my_data]
Description = Connection to windows virtual machine
Driver = TDS
Trace = No
Database = testdb
Server = 192.168.0.2
Port = 1433
TDS_Version = 8.0
[my_data]一行意为开始定义一个名叫my_data的数据源。Driver属性指定的名字是预定义好的TDS驱动,其他是一些数据库的相关属性,如服务器地址,端口等。
现在把tds.datasource.template文件里定义的数据源安装到系统的ODBC数据源中,执行下面的命令:
root@ubuntu:/home/jeff# odbcinst -i -s -l -f tds.datasource.template
-i 表示install,安装
-s 表示source,所安装的是数据源
-l 表示把数据源安装到系统的全局数据源配置文件,用-h则是安装到用户的数据源配置文件中
-f 表示file,指定要安装的文件
OK,把驱动和数据源都安装好了,现在来测试一下通过ODBC访问SQL Server如何吧,使用unixODBC自带的isql命令,使用格式为: isql 数据源名 用户名 密码
root@ubuntu:/home/jeff# isql my_data sa password
+---------------------------------------+
| Connected! |
| |
| sql-statement |
| help [tablename] |
| quit |
| |
+---------------------------------------+
SQL>
如果你看下上面类似的画面,说明ODBC和SQL Server现在沟通得很好,这时你可以在SQL>提示符下输入Sql语句试一把,感觉High吧?还有一步,我们就成功了。
三、安装odbc协议的python实现--pyodbc
到这里下载pyodbc,解原缩后使用python install.py setup来安装,如果一切顺利那就恭喜你了,如果安装过程报错,那你一定是少了一些什么!我安装pyodbc也装了蛮久才成功,我的经验是:如果报错,检查一下你的系统是否安装了下面的一些lib,如果没有请通过apt-get install来安装:
g++,unixODBC-dev,python-dev
好,到这里假设pyodbc已经安装完毕了。那么,照这里测试一下吧!整个过程就这样分三步走,每一步做完都要保证测试通过,这样中间出错的话,问题也容易定位得多了!
目标达成!不过,当我把这过程写完的时候反而觉得这是小菜一碟了。。。囧。。希望自己没有小题大作,希望对将来不幸要折腾Sql Server的同学有所帮助。
参考文档:
来自赖总的经验:http://blog.csdn.net/lanphaday/archive/2009/01/20/3838967.aspx
和这位老外兄弟就mac上的连接问题沟通了几次,他这篇linux+mssql的文档值得一读:http://blog.singletoned.net/2009/07/connecting-to-ms-sql-server-from-python-on-linux/
http://code.google.com/p/pyodbc/
http://www.unixodbc.org/doc/FreeTDS.html
还有很多数不胜数的maillist归档和网页。感谢互联网,感谢google。
第三届广州技术沙龙札记之图片篇
第三届广州技术沙龙再次完美落幕,易度的老潘和金山的刘老师再次献上精彩的Topic,分别是《云时代软件》与及《PostgreSQL数据库及相关设计》。听老潘讲东西那么久,今天这个Topic真是听出耳油,老潘的幻灯和组织功夫越来越好了,赞!刘老师讲的PostgreSQL估计是本次沙龙感兴趣人数最多的了,好多同学冲着这个Topic而来的哦!今天在这里先共享PP,接下来有空再补上心得吧。感谢主办本次沙龙的同学们!
一、赖总勇浩,技术沙龙的主办者之一。辛苦辛苦!

二、老潘在讲《云计时的软件》,老潘,润普公司技术总监,现易度网的核心人物。

三、课间一位美女插进一脚,给Python做做广告:“咱们基金买卖网自从用了Python之后,开发人员少了,赚钱多了”!,原来基金买卖网的技术先锋是CPUG的VCC兄。

四、People Not Found!geekcook是这一次沙龙的赞助商之一,所送的小礼物很有意思。有Geek的味道。图片是Benky Not Found!

五、自报家门时间,这次的自我介绍放在两个Topic中间了。这次还是很多网易、TENCEN、Kingsoft的同学们啊。。

六、又见美女!继上一次在网易参加了第二次技术沙龙后,这位美女程序员再次露面,并和一边的老甘同学打得火热,老甘当仁不让地发挥老前辈的指导精神,与陆小同学打成一片。

七、刘鑫老师介绍PostgreSQL,原来Postgres真的很好很强大,刘老师让俺有动力花课余时间去研究研究她。

八、Postgres VS Zope DB。Benky一席问话,又挑起老潘同志的激情,再次上台撒播ZopeDB,赖总在下面说,好有激情啊!看老潘的陶醉样。。嘿。

九、小合照。按照常规的会课和沙龙约定,会后都要照张合照。这次没在会场照,而是到了大堂才想起要来张合照,只好来一张小的合照。

以上是沙龙的照片不完整版,不代表本次沙龙的全貌,敬请见谅。更多的图片请稍候,晚点再放出来,而此次沙龙的视频及录音,等沙龙官方主办的同学释出吧。
PS。本次的场地是中大西门的北大青鸟教室,两年前在此,因为Python的会课认识了一帮朋友并交往至今,实属缘份,以后,希望在广州技术沙龙里认识更多志同道合的朋友们。