Pyramid找到我们项目的main函数之后,一切就相对简单了。
一、项目参数的传递
我们打开项目中的__init__.py文件,找到自动生成的main函数如下:
我们可以看到,main函数带了两个参数,global_config和setting。这是由Paste deploy传递过来的解析自development.ini的参数项。
其中global_config是development.ini中[DEFAULT]这一节中的参数定义,在我们自动生成的例子中,我们没有使用default节,所以也就没有传入自定义的参数,系统默认在global_config这个字典对象中加了两个参数项定义:
here: 表示development.ini文件所在目录的绝对路径
__file__: 表示development.ini文件的绝对路径
setting字典则包含了所有定义在[app:main]中的参数项(除了use),在我们的例子中,就包含了pyramid.reload_templates、pyramid.debug_authorization、sqlalchemy.url等的参数项。这些参数项都可以直接在我们的程序中使用。我们也可以在[app:main]中定义自定义的参数项,如mytest=testconfig。那么我们在view中就可以用如下程序取得定义的值。
settings = request.registry.settings
mytest = settings[’mytest’]
这里注意一下,放在其他section中的参数是传不进来的,如果一定要这样用,需要在程序中取到ini文件路径(global_config中的__file__),然后自行使用ConfigParser读取解析。
二、Configurator的配置
就如上面的程序,main函数做的最主要的工作就是做整合项目的配置,形成注册表。在Pyramid中可以配置的东西很多,我们可以简单看下几个常用的配置:
1. 静态资源
通过config.add_static_view('static', 'static', cache_max_age=3600)加入一个静态资源目录,一般写成config.add_static_view(name=’static’, path=’/var/www/static’) 或 config.add_static_view(name=’static’, path=’mypackage:a/b/c/static’) 这样的方式更清晰。
在add_static_view中,name代表了静态文件URL的前缀,如果我们使用了上面前一个例子,那么URL /static/foo.css 就会取指向文件/var/www/static/foo.css。后一个例子是相对与项目包结构的相对路径。
不过现在很多程序都是用外部资源来做静态资源的,也可以用config.add_static_view(name=’http://example.com/images’, path=’mypackage:static’)这种方式将静态文件指向外部服务器。
在程序中,就可以用static_url('pyramidkoans:static/favicon.ico') 或 static_path('pyramidkoans:static/favicon.ico') 这样的方式来引用静态资源。按照之前不同的定义,这里会解析出不同的结果。
2. add_route、add_view、view_config、scan
这几个函数定义了从URL到view的映射关系,add_route只在Route模式才会使用,traversal模式下不用。
view的配置可以使用add_view手工加入,也可以使用view_config标注+scan函数合作完成。
3. 权限
pyramid整合了一套ACL权限管理体系,也需要在configurtor中进行配置才能生效。pyramid权限管理划分了认证、授权两个部分,需要分别配置。
authn_policy = AuthTktAuthenticationPolicy('sosecret', callback=groupfinder)
authz_policy = ACLAuthorizationPolicy()
config.set_authentication_policy(authn_policy)
config.set_authorization_policy(authz_policy)
4. 用include包含子模块
项目大了之后,可以划分成多个子模块,然后用include包含子模块。
5.subscriber
Pyramid定义了一套简单的事件系统,开发者可以通过订阅一些特定的事件来改变框架的一些默认行为。
三、app的生成
完成了configurator的配置之后,pyramid就调用make_wsgi_app来生成一个符合WSGI规范的app,以便提供服务。
不过这个app是一个叫Router的类的实例,很奇怪吧。
好了,接下来就等待访问链接的来临吧
Thursday, March 22, 2012
Wednesday, March 21, 2012
利用Amazon SES为应用构建简单的邮件服务
Amazon SES是AWS推出的一项邮件发送服务,类似于sendgrid等专业的邮件发送服务商。不过因AWS众多其他服务的捆绑支持,对于AWS平台上的应用还是具有不小的吸引力的。
一. 为啥使用SES呢
1. 对于发送量不稳定的应用,价格还是便宜的,发多少,算多少($0.10/1000条),没有套餐限制,附带流量也会产生费用。
2. 对于AWS EC2上的应用,有每天2000封的免费额度,基本足够大部分人使用了。
当然,也要牢记,amazon不是专业的mail发送公司,涉及到更专业的送达服务、垃圾邮件等方面还不那么健全,普通用用是完全没问题的,毕竟大家都知道邮件是怎么回事,有点小问题也都能谅解,顶多勤快点,多泡泡amazon服务论坛。
二. SES接入模式
amazon提供了多种接入支持以满足各种不同的需要:
1. smtp发送服务,提供了STARTTLS、TLS Wrapper两种不同方式,端口不同,可以用于编程或安装应用软件配置
2. api发送服务,可以通过amazon的api发送邮件,这里提供了一个封装。https://github.com/pankratiev/python-amazon-ses-api/blob/master/amazon_ses.py3. 与 Postfix 整合,配置其relayhost参数,使已有的应用能方便的使用SES服务能力。
三. smtp接入案例
1. 发件人认证
SES需要对每一个发件人邮箱进行认证,不存在的发件人不能够发送邮件。只需要再verify a new sender里面输入邮件地址,SES会往这个邮箱发送一个验证URL,在浏览器打开该URL即可完成验证。
SES 工作在sanbox状态下,需要同时将收信人也进行同样的认证。如果需要在生产环境使用,需要事先申请,24小时开通。
2. 生成SMTP 用户密码对
在发信之前,还需要生成一个smtp用户密码对,只需要点击SMTP Settings 中的Create My SMTP Credentials按钮即可在IAM中生成一个账号,同时显示其名字、密码,记录下来保存好需要在发送邮件时使用。
3. 小程序
mailServer = smtplib.SMTP_SSL('email-smtp.us-east-1.amazonaws.com', 465)
mailServer.set_debuglevel(1)
mailServer.login(IAM用户名, IAM用户密码)
mailServer.sendmail('发件人', ['收件人'], msg.as_string())
mailServer.close()
一. 为啥使用SES呢
1. 对于发送量不稳定的应用,价格还是便宜的,发多少,算多少($0.10/1000条),没有套餐限制,附带流量也会产生费用。
2. 对于AWS EC2上的应用,有每天2000封的免费额度,基本足够大部分人使用了。
当然,也要牢记,amazon不是专业的mail发送公司,涉及到更专业的送达服务、垃圾邮件等方面还不那么健全,普通用用是完全没问题的,毕竟大家都知道邮件是怎么回事,有点小问题也都能谅解,顶多勤快点,多泡泡amazon服务论坛。
二. SES接入模式
amazon提供了多种接入支持以满足各种不同的需要:
1. smtp发送服务,提供了STARTTLS、TLS Wrapper两种不同方式,端口不同,可以用于编程或安装应用软件配置
2. api发送服务,可以通过amazon的api发送邮件,这里提供了一个封装。https://github.com/pankratiev/python-amazon-ses-api/blob/master/amazon_ses.py3. 与 Postfix 整合,配置其relayhost参数,使已有的应用能方便的使用SES服务能力。
三. smtp接入案例
1. 发件人认证
SES需要对每一个发件人邮箱进行认证,不存在的发件人不能够发送邮件。只需要再verify a new sender里面输入邮件地址,SES会往这个邮箱发送一个验证URL,在浏览器打开该URL即可完成验证。
SES 工作在sanbox状态下,需要同时将收信人也进行同样的认证。如果需要在生产环境使用,需要事先申请,24小时开通。
2. 生成SMTP 用户密码对
在发信之前,还需要生成一个smtp用户密码对,只需要点击SMTP Settings 中的Create My SMTP Credentials按钮即可在IAM中生成一个账号,同时显示其名字、密码,记录下来保存好需要在发送邮件时使用。
3. 小程序
mailServer = smtplib.SMTP_SSL('email-smtp.us-east-1.amazonaws.com', 465)
mailServer.set_debuglevel(1)
mailServer.login(IAM用户名, IAM用户密码)
mailServer.sendmail('发件人', ['收件人'], msg.as_string())
mailServer.close()
Tuesday, March 20, 2012
Pyramid项目是怎么启动起来的?
Pyramid 官方文档上专门有一个章节解释了Pyramid项目的启动过程,不过因为整个启动过程还涉及到一些非pyramid模块,光看那个说明未必能很好理解清楚整个启动过程。下面,我们通过一个小例子简单看看一个Pyramid项目是怎么一步一步启动起来的。
一、创建好项目,配置好开发环境。
按照pyramid的介绍,我们用如下命令很快就可以创建一个演示项目。
pcreate -s alchemy PyramidKoans
python setup.py develop
Ok,现在就可以用
pserve development.ini来启动这个项目了。
二、pserve是啥?
问题来了,为什么是用pserve来启动?pserve又是怎么启动载入的呢?
我们知道,pyramid安装的时候会在/bin目录下(如果你用virtualenv的话)生成一堆的执行文件,pserve就是其中一个,我们打开看看先:
这堆文件基本都是这个样子,只是里面参数有差异而已,其实这些都是easy_install根据egg包中的egg_info自动生成的,所以当然都差不多啦。
下面我们再打开pyramid EGG_INFO中的entry_points.txt文件对比一下:
可以看到在/bin下生成的执行文件跟上面console_scripts是一一对应的。
所以,我们就可以很好理解 load_entry_point('pyramid==1.3b2', 'console_scripts', 'pserve')() 这语句了,它就是来pyramid 1.3b2这个egg包中来找'console_scripts', 'pserve'这个入口,然后载入其对应的程序,这里就是pyramid.scripts.pserve:main。
再打开pyramid包script目录下,找到pserve.py找到main函数,刚才的pserve命令就是启动了这个main函数而已。(其实这个script就是原来的paste script内容,基本原封不动的转到这里来了。)
二、paste deploy来了
既然用了paste script,那当然就要用到paste deploy啦。
找到PServeCommand类的run方法,很容易就可以找到
这就是用了paste deploy中的loadserver,loadapp方法。
paste deploy是一个很常用定位、配置WSGI应用/服务器的工具包,它可以从一个定制的配置文件里面载入你所定义的app和server。这里这个配置文件就是上面启动命令里面提到的development.ini。加载了app和server之后,马上可以看到
因为这里的server跟app都是符合WSGI标准的,所有将app丢给server即可启动啦。
三、development.ini
上面已经找到了server和app的载入,那么又是怎么找到你所需要的那个server跟app呢?要理解这点,就需要看development.ini这个配置文件了。
这是一个基本上算标准的ini配置文件,不过paste deploy还是在上面做了一些定制。比如server:main、app:main、use这些定义。
server:main
这里的server是一个固定用法,表示下面的配置用于启动一个WSGI server。
server:main这一配置块定义了WSGI server启动方式以及它的启动参数,如host、port。
这里的第一行use = egg:waitress#main就是定义了如何启动WSGI server。这里use也是个固定用法,egg:waitress#main表示找到waitress这个egg包,找到里面的entry_points中main定义项:
然后查看waitress这个包中的serve_paste这个方法即可,这个方法就是将waitress这个WSGI server启动起来。具体的waitress内容这里就不详细讨论了。
在定义waitressa参数的时候要注意下,我们经常还需要定义一个threads参数,它表示需要启动多少线程来提供服务,默认是4个,如果需要在正式环境用的话是不够的。
当然,我们也可以通过修改配置重新使用paste来替换waitress提供服务。
app:main
这里app也是固定用法,表示app_factory,表示由这里的信息来生成WSGI app。main是配置块名字,在使用pipeline的时候用得到。
app:main块定义了app中所能使用的参数(除了use),如pyramid.reload_templates、pyramid.debug_templates、sqlalchemy.url…这些都是pyramid本身或app程序中需要使用的配置,如果app需要定义自己的配置,也可以放在这里。
这里我们要着重看一下的是use = egg:PyramidKoans这句。egg:PyramidKoans表示从PyramidKoans这个egg包找到app的入口,这里省略了#main(默认就是它啦)。所以,又要找entry point啦,打开PyramidKoans项目中的setup.py文件(没打包发行之前,entry_points存在这里面。),
我们在这里也找到了entry_points,看[paste.app_factory]这里的定义,paste deploy就是来找这一段配置,再看main = pyramidkoans:main,这里第一个main就是我们刚才说的省略了的那个main,然后它指向了 pyramidkoans:main,表示需要到paramidkoans这个包里去找main这个方法。
终于走到我的程序了!
一、创建好项目,配置好开发环境。
按照pyramid的介绍,我们用如下命令很快就可以创建一个演示项目。
pcreate -s alchemy PyramidKoans
python setup.py develop
Ok,现在就可以用
pserve development.ini来启动这个项目了。
二、pserve是啥?
问题来了,为什么是用pserve来启动?pserve又是怎么启动载入的呢?
我们知道,pyramid安装的时候会在
这堆文件基本都是这个样子,只是里面参数有差异而已,其实这些都是easy_install根据egg包中的egg_info自动生成的,所以当然都差不多啦。
下面我们再打开pyramid EGG_INFO中的entry_points.txt文件对比一下:
可以看到在
所以,我们就可以很好理解 load_entry_point('pyramid==1.3b2', 'console_scripts', 'pserve')() 这语句了,它就是来pyramid 1.3b2这个egg包中来找'console_scripts', 'pserve'这个入口,然后载入其对应的程序,这里就是pyramid.scripts.pserve:main。
再打开pyramid包script目录下,找到pserve.py找到main函数,刚才的pserve命令就是启动了这个main函数而已。(其实这个script就是原来的paste script内容,基本原封不动的转到这里来了。)
二、paste deploy来了
既然用了paste script,那当然就要用到paste deploy啦。
找到PServeCommand类的run方法,很容易就可以找到
这就是用了paste deploy中的loadserver,loadapp方法。
paste deploy是一个很常用定位、配置WSGI应用/服务器的工具包,它可以从一个定制的配置文件里面载入你所定义的app和server。这里这个配置文件就是上面启动命令里面提到的development.ini。加载了app和server之后,马上可以看到
因为这里的server跟app都是符合WSGI标准的,所有将app丢给server即可启动啦。
三、development.ini
上面已经找到了server和app的载入,那么又是怎么找到你所需要的那个server跟app呢?要理解这点,就需要看development.ini这个配置文件了。
这是一个基本上算标准的ini配置文件,不过paste deploy还是在上面做了一些定制。比如server:main、app:main、use这些定义。
server:main
这里的server是一个固定用法,表示下面的配置用于启动一个WSGI server。
server:main这一配置块定义了WSGI server启动方式以及它的启动参数,如host、port。
这里的第一行use = egg:waitress#main就是定义了如何启动WSGI server。这里use也是个固定用法,egg:waitress#main表示找到waitress这个egg包,找到里面的entry_points中main定义项:
然后查看waitress这个包中的serve_paste这个方法即可,这个方法就是将waitress这个WSGI server启动起来。具体的waitress内容这里就不详细讨论了。
在定义waitressa参数的时候要注意下,我们经常还需要定义一个threads参数,它表示需要启动多少线程来提供服务,默认是4个,如果需要在正式环境用的话是不够的。
当然,我们也可以通过修改配置重新使用paste来替换waitress提供服务。
app:main
这里app也是固定用法,表示app_factory,表示由这里的信息来生成WSGI app。main是配置块名字,在使用pipeline的时候用得到。
app:main块定义了app中所能使用的参数(除了use),如pyramid.reload_templates、pyramid.debug_templates、sqlalchemy.url…这些都是pyramid本身或app程序中需要使用的配置,如果app需要定义自己的配置,也可以放在这里。
这里我们要着重看一下的是use = egg:PyramidKoans这句。egg:PyramidKoans表示从PyramidKoans这个egg包找到app的入口,这里省略了#main(默认就是它啦)。所以,又要找entry point啦,打开PyramidKoans项目中的setup.py文件(没打包发行之前,entry_points存在这里面。),
我们在这里也找到了entry_points,看[paste.app_factory]这里的定义,paste deploy就是来找这一段配置,再看main = pyramidkoans:main,这里第一个main就是我们刚才说的省略了的那个main,然后它指向了 pyramidkoans:main,表示需要到paramidkoans这个包里去找main这个方法。
终于走到我的程序了!
Wednesday, August 10, 2011
快速建立Pylons CI环境
因目前业务还跑在Pylons上,因此就拿Pylons来做这个例子吧。其他Python环境应该也是大同小异的。
CI系统环境:
OS: Ubuntu
CI 工具: Hudson 1.396
单元测试工具: nosetests
Hudson 本身的安装使用就不细写了,网上现在已经有很多了。直接下载war包,用java -jar运行即可。
启动之后,在管理界面中安装 Hudson Cobertura plugin、Python Plugin、Hudson Violations plugin、Subversion Plugin等插件即可。
一、建立虚拟环境
为了使Hudson同时支持多个python项目的持续集成,建议为每一个项目建立独立的虚拟环境,以便更清楚与项目相关联的包的情况,方便今后的部署。
下面几个步骤即可建立一个基本的虚拟环境。
1. 找到virtualenv包,取出其中的virtualenv.py
2. 运行python virtualenv.py --no-site-packages pylons-0.9.7 建立一个名字叫pylons-0.9.7的虚拟环境。这里 --no-site-packages参数是为了排除linux系统自带的python包对项目的影响,加了这个参数即可建立比较干净的Python虚拟环境。
3. 启动刚才建立的虚拟环境 source pylons-0.9.7/bin/activate
4. 运行easy_install nose 安装nosetests单元测试工具
5. 运行easy_install fudge 安装fudge Mock工具
6. 运行easy_install nosexcover 安装覆盖率生成工具,这个工具可以生成hudson中需要的xml格式的报表。仅仅安装coverage包不能生成类似报表。
二、建立项目运行环境
现在一个基本的环境已经基本建立完成了。下面在安装一些该项目特定的包
1. 安装mysql python包、sqlalchemy包
sudo apt-get install libmysqlclient-dev (MySQL-python编译安装需要mysql client开发环境)
easy_install MySQL-python
easy_install "sqlalchemy==0.5.8"
2. 安装pylons
easy_install -Z "pylons==0.9.7"
在pylons-0.9.7/lib/python26/site-packages/WebOb-1.1beta1-py2.6.egg/webob/__init__.py中加入一行from webob.multidict import UnicodeMultiDict
(pylons下载了最新的webob,里面有些改动,pylons 0.9.7不支持,需要改下)
3. 再按装写杂七杂八的项目用到的包
easy_install pycrypto
easy_install recaptcha_client
easy_install python-memcached
好了,一个pylons虚拟环境基本完成了,可以先直接下载项目代码运行nosetests看看有没有什么问题,如果运行都正常,即可进行以下步骤
三、建立Hudsong项目
1. 在Hudson中新建一个任务,选择“构建一个自由风格的软件项目“
2. 输入代码地址(SVN/CVS...)
3. 按照crontab规则建立build规律
4. 选择shell脚本作为build命令,在里面输入如下内容:
. /home/mm/pylons-0.9.7/bin/activate
cd ${WORKSPACE}
nosetests --cover-package=包名 --cover-tests --with-xcoverage --with-xunit --verbose
注:这里报名替换成需要测试覆盖率的包名
5. 设置输出报表
Publish JUnit test result report
xml文件直接输入 nosetests.xml
Publish Cobertura Coverage Report
xml文件直接输入 coverage.xml
CI系统环境:
OS: Ubuntu
CI 工具: Hudson 1.396
单元测试工具: nosetests
Hudson 本身的安装使用就不细写了,网上现在已经有很多了。直接下载war包,用java -jar运行即可。
启动之后,在管理界面中安装 Hudson Cobertura plugin、Python Plugin、Hudson Violations plugin、Subversion Plugin等插件即可。
一、建立虚拟环境
为了使Hudson同时支持多个python项目的持续集成,建议为每一个项目建立独立的虚拟环境,以便更清楚与项目相关联的包的情况,方便今后的部署。
下面几个步骤即可建立一个基本的虚拟环境。
1. 找到virtualenv包,取出其中的virtualenv.py
2. 运行python virtualenv.py --no-site-packages pylons-0.9.7 建立一个名字叫pylons-0.9.7的虚拟环境。这里 --no-site-packages参数是为了排除linux系统自带的python包对项目的影响,加了这个参数即可建立比较干净的Python虚拟环境。
3. 启动刚才建立的虚拟环境 source pylons-0.9.7/bin/activate
4. 运行easy_install nose 安装nosetests单元测试工具
5. 运行easy_install fudge 安装fudge Mock工具
6. 运行easy_install nosexcover 安装覆盖率生成工具,这个工具可以生成hudson中需要的xml格式的报表。仅仅安装coverage包不能生成类似报表。
二、建立项目运行环境
现在一个基本的环境已经基本建立完成了。下面在安装一些该项目特定的包
1. 安装mysql python包、sqlalchemy包
sudo apt-get install libmysqlclient-dev (MySQL-python编译安装需要mysql client开发环境)
easy_install MySQL-python
easy_install "sqlalchemy==0.5.8"
2. 安装pylons
easy_install -Z "pylons==0.9.7"
在pylons-0.9.7/lib/python26/site-packages/WebOb-1.1beta1-py2.6.egg/webob/__init__.py中加入一行from webob.multidict import UnicodeMultiDict
(pylons下载了最新的webob,里面有些改动,pylons 0.9.7不支持,需要改下)
3. 再按装写杂七杂八的项目用到的包
easy_install pycrypto
easy_install recaptcha_client
easy_install python-memcached
好了,一个pylons虚拟环境基本完成了,可以先直接下载项目代码运行nosetests看看有没有什么问题,如果运行都正常,即可进行以下步骤
三、建立Hudsong项目
1. 在Hudson中新建一个任务,选择“构建一个自由风格的软件项目“
2. 输入代码地址(SVN/CVS...)
3. 按照crontab规则建立build规律
4. 选择shell脚本作为build命令,在里面输入如下内容:
. /home/mm/pylons-0.9.7/bin/activate
cd ${WORKSPACE}
nosetests --cover-package=包名 --cover-tests --with-xcoverage --with-xunit --verbose
注:这里报名替换成需要测试覆盖率的包名
5. 设置输出报表
Publish JUnit test result report
xml文件直接输入 nosetests.xml
Publish Cobertura Coverage Report
xml文件直接输入 coverage.xml
Sunday, August 7, 2011
code review 之我见
近期code review的讨论貌似很多,也来凑下热闹,说说自己的一些认识和想法。
一、常见误区
1. 在我经历过的很多团队中,貌似不少人员都认为code review是一种上级的管理手段。毕竟翻译成中文叫“代码评审
”,这又评又审的,很多人就已经开始心里打鼓了,这嘴上不说,心底里早就开始抵触上了。这种情绪下还能指望即时
的review么?
2. code review不能算是考核工具,很多管理者都会有review出一个问题,扣多少多少类似的想法,把review简简单单
的当成了抓虫子,从而造成了更多的开发人员的抵触。一review就变味成了给开发挑刺,然后升级成双方攻防战,搞得
面红耳赤,你死我活的,最后一拍两散。
3. code review也不是个人技术挑战赛,这在很多年轻气盛的开发人员中很常见,“凭什么给他看”,“他又看不懂”
是这类人经常会说的话。其实从来没有人规定过review一定要找更厉害的人,一定要找出问题来的。
4. review是每一个团队成员的事,而不仅仅是经理或者架构师的事。这在传统的开发团队里面很常见,代码开发完了
一丢,就没自己啥事了。在敏捷开发中,review应该是每一个成员自发的行为。
二、一点想法
1. 整个团队必须保持一个开放的心态,能够虚心听取他人意见,战斗的团队是指对外战斗,不是内斗。
2. 必须建立一个前提认识:代码共享,团队中每个人都能随时浏览他人最新代码。代码不是私人物品,不能敝帚自珍。
3. 明确一个观点:任何review都不是挑错,是一种相互探讨,追求更高质量,更优代码的过程,是团队共同进步的一种手段。
4. review中每个人都是平等的,没有谁服从谁的概念。每个参与review的人要有包容的心态,不是只有你的解决办法是最优的
5. 得有一个公认的代码标准,最好能持续维护一个知识库,将一些优秀的代码、历史的review经验积累起来。
6. review要经常化,每次review的量要小,最好完成一个功能就review它。一次review一整个项目任谁都会烦。
7. 提交代码的时候要写清楚,也要有点必要的注释或文档,不要让别人去猜,浪费大家时间。
一、常见误区
1. 在我经历过的很多团队中,貌似不少人员都认为code review是一种上级的管理手段。毕竟翻译成中文叫“代码评审
”,这又评又审的,很多人就已经开始心里打鼓了,这嘴上不说,心底里早就开始抵触上了。这种情绪下还能指望即时
的review么?
2. code review不能算是考核工具,很多管理者都会有review出一个问题,扣多少多少类似的想法,把review简简单单
的当成了抓虫子,从而造成了更多的开发人员的抵触。一review就变味成了给开发挑刺,然后升级成双方攻防战,搞得
面红耳赤,你死我活的,最后一拍两散。
3. code review也不是个人技术挑战赛,这在很多年轻气盛的开发人员中很常见,“凭什么给他看”,“他又看不懂”
是这类人经常会说的话。其实从来没有人规定过review一定要找更厉害的人,一定要找出问题来的。
4. review是每一个团队成员的事,而不仅仅是经理或者架构师的事。这在传统的开发团队里面很常见,代码开发完了
一丢,就没自己啥事了。在敏捷开发中,review应该是每一个成员自发的行为。
二、一点想法
1. 整个团队必须保持一个开放的心态,能够虚心听取他人意见,战斗的团队是指对外战斗,不是内斗。
2. 必须建立一个前提认识:代码共享,团队中每个人都能随时浏览他人最新代码。代码不是私人物品,不能敝帚自珍。
3. 明确一个观点:任何review都不是挑错,是一种相互探讨,追求更高质量,更优代码的过程,是团队共同进步的一种手段。
4. review中每个人都是平等的,没有谁服从谁的概念。每个参与review的人要有包容的心态,不是只有你的解决办法是最优的
5. 得有一个公认的代码标准,最好能持续维护一个知识库,将一些优秀的代码、历史的review经验积累起来。
6. review要经常化,每次review的量要小,最好完成一个功能就review它。一次review一整个项目任谁都会烦。
7. 提交代码的时候要写清楚,也要有点必要的注释或文档,不要让别人去猜,浪费大家时间。
Tuesday, August 2, 2011
Pyramid 学习笔记:创建Pyramid项目(下)
除了在项目根目录生成了一系列项目配置性文件之外,Pyramid还生成了一个简单的项目框架结构以方便开发人员编写代码。这些文件统一放在了myproject这个目录下面。
一、__init__.py文件
该文件主要定义了项目入口方法。主要代码如下:
这个main函数是Pyramid自动生成的本项目的入口,这里global_config, settings两个参数分别对应于development.ini(或production.ini)中的DEFAULT段和app:myproject段的内容。本函数主要功能就是完成了使用traversal机制进行URL映射的配置过程。traversal机制是受zope启发而来的一种URL映射机制,可以构建比较复杂的URL结构。如果URL结构比较简单的化,可以使用ROUTE机制,比较直观一点。
该函数最后返回一个WSGI应用以启动本应用。
二、view.py文件
Pyramid应用中的大部分实现都是在view中实现的,这个可以看作pylons中的controller。在我们生成的项目中,view.py只有一个简单的函数:
def my_view(request):
return {'project':'myproject'}
在前面提到的__init__.py中,我们通过add_view函数注册到了系统中。因此运行这个应用之后,直接浏览 / 看到的就是调用了这个函数而返回的结果(经模板渲染之后)。
三、resources.py文件
这个文件就是用于traversal机制来映射URL时提供站点结构等资源的文件。我们通常用一个Root类来表示这些资源的根。每次接到WEB请求的时候,Pyramid Router通过这个类来找到本项目资源树的根。
四、静态文件目录
主要包含CSS、图片等静态文件
五、模板目录
存放项目开发用的模板文件。这也是在__init__.py中被add_view注册到系统中,并且与一个view关联。
六、test.py
这就是单元测试文件。
Pyramid生成的这个项目框架其实是很简单的一个结构,基本上是无法满足我们项目开发的需要的,一般我们都会修修改改再在项目中使用,也可以修改后生成一套scaffold以便今后重复利用。
一般情况下,我们都会做如下修改:
* view包,以及多层的包结构,如果应用比较复杂的话。
* 单元测试包结构
* URL映射如果复杂的化最好也能独立出来
* lib包,如果需要的话
* model包,如果有数据库支持的话
总体感觉,Pyramid生成的代码在项目代码结构的指导意义上不如pylons,也没Pylons那么严谨周全,要动的东西很多,需要抽个时间好好整理一个能用的东西出来。
本文提到的示例材料均源于Pyramid官方网站
一、__init__.py文件
该文件主要定义了项目入口方法。主要代码如下:
def main(global_config, **settings): """ This function returns a Pyramid WSGI application. """ config = Configurator(root_factory=Root, settings=settings) config.add_view(’myproject.views.my_view’, context=’myproject.resources.Root’, renderer=’myproject:templates/mytemplate.pt’) config.add_static_view(’static’, ’myproject:static’) return config.make_wsgi_app()
这个main函数是Pyramid自动生成的本项目的入口,这里global_config, settings两个参数分别对应于development.ini(或production.ini)中的DEFAULT段和app:myproject段的内容。本函数主要功能就是完成了使用traversal机制进行URL映射的配置过程。traversal机制是受zope启发而来的一种URL映射机制,可以构建比较复杂的URL结构。如果URL结构比较简单的化,可以使用ROUTE机制,比较直观一点。
该函数最后返回一个WSGI应用以启动本应用。
二、view.py文件
Pyramid应用中的大部分实现都是在view中实现的,这个可以看作pylons中的controller。在我们生成的项目中,view.py只有一个简单的函数:
def my_view(request):
return {'project':'myproject'}
在前面提到的__init__.py中,我们通过add_view函数注册到了系统中。因此运行这个应用之后,直接浏览 / 看到的就是调用了这个函数而返回的结果(经模板渲染之后)。
三、resources.py文件
这个文件就是用于traversal机制来映射URL时提供站点结构等资源的文件。我们通常用一个Root类来表示这些资源的根。每次接到WEB请求的时候,Pyramid Router通过这个类来找到本项目资源树的根。
四、静态文件目录
主要包含CSS、图片等静态文件
五、模板目录
存放项目开发用的模板文件。这也是在__init__.py中被add_view注册到系统中,并且与一个view关联。
六、test.py
这就是单元测试文件。
Pyramid生成的这个项目框架其实是很简单的一个结构,基本上是无法满足我们项目开发的需要的,一般我们都会修修改改再在项目中使用,也可以修改后生成一套scaffold以便今后重复利用。
一般情况下,我们都会做如下修改:
* view包,以及多层的包结构,如果应用比较复杂的话。
* 单元测试包结构
* URL映射如果复杂的化最好也能独立出来
* lib包,如果需要的话
* model包,如果有数据库支持的话
总体感觉,Pyramid生成的代码在项目代码结构的指导意义上不如pylons,也没Pylons那么严谨周全,要动的东西很多,需要抽个时间好好整理一个能用的东西出来。
本文提到的示例材料均源于Pyramid官方网站
Sunday, July 31, 2011
Pyramid 学习笔记:创建Pyramid项目(中)
需要深入理解Pyramid(Pylons也一样)项目结构,至少需要了解Paste项目的一些必要信息,也要对setuptools有一定了解,否则很多东西都会知其然而不知其所以然。
我们先简单看看一个基本Pyramid项目中各个文件的作用与基本内容。
一、development.ini配置文件结构
development.ini是一个PasteDeploy配置文件,主要为使用paster serve运行的应用提供配置参数。我们安装development.ini中配置段落逐项看一下其具体的作用。
[server:main]
use = egg:Paste#http
host = 0.0.0.0
port = 6543
这一段定义了WSGI服务器的一些基本信息。
use = egg:Paste#http表明使用Paste中的http服务器来为应用提供服务。
host = 0.0.0.0表示任何IP地址都可以访问这个应用
port = 6543表示服务端口是6543
在[server:main]里面还可以配置http服务器线程池等各种参数,具体可以查看PasteDeplay。
[pipeline:main]
pipeline =
egg:WebError#evalerror
MyProject
这也是PasteDeplay中定义的格式。这一段定义了paster serve命令运行的应用(这里是一个管道)。
[app:MyProject]
use = egg:MyProject
reload_templates = true
debug_authorization = false
debug_notfound = false
debug_routematch = false
debug_templates = true
default_locale_name = en
这一段就是本应用的配置参数。注意,这里的名字MyProject与pineline中定义的名字一致。
在本段配置参数中,use = egg:MyProject 这里省略了#main(即use = egg:MyProject#main)。这个定义指明了本应用的入口程序,这里是MyProject这个egg包中的main函数(可以查看myproject目录下的__init__.py文件,里面就定义了这个main函数)。
另外还有reload_templates、debug_templates也需要注意一下,这主要是在开发中调试方便使用的,在应用部署时记得设成false。
development.ini中还有一大段python 标准log信息的配置,都懂得,不解释。
二、production.ini
Pyramid还加了一个产品部署时用的配置文件production.ini,基本等同与development.ini。主要区别是去掉了WebError交互调试界面,以及一些调试开关。
三、MANIFEST.in文件
这是distutils这个打包工具的配置文件(setuptools是distutils的一个扩展)。主要在里面列出了一些需要打进egg包的非python文件。
四、setup.py
这是运行setuptools所需要的启动文件。我们在单元测试、打包、分发等工作时经常需要使用它。这基本已经是python世界里面的事实标准了。
在这个文件里面,我们需要注意的配置项如下:
name=’MyProject’ 项目名,包名
version=’0.0’ 版本,这个经常需要改动
packages=find_packages() 打包时需要打到包中的内容,默认所有
zip_safe=False 指定该包是否能够不解压就能被引用
install_requires=requires, tests_require=requires 指定了本项目的依赖关系,需要什么包才能安装、测试
test_suite="myproject" 指定了单元测试搜索路径
entry_points 定义了本项目的入口。
定义好我们就可以使用
python setup.py sdist
这样的命令将整个项目打包。不同的打包命令及其区别参见setuptools
五、setup.cfg
这个文件是setuptools的参数配置文件,主要配置了单元测试、国际化等方面的一些配置。
[nosetests]
match = ^test
nocapture = 1
cover-package = myproject
with-coverage = 1
cover-erase = 1
这一段是单元测试的配置信息(不过貌似跟python setup.py test命令无关,目前还不清楚在什么地方用到。
其他的信息都是国际化支持的配置,这跟标准python中定义的基本相同。
本文提到的示例材料均源于Pyramid官方网站
我们先简单看看一个基本Pyramid项目中各个文件的作用与基本内容。
一、development.ini配置文件结构
development.ini是一个PasteDeploy配置文件,主要为使用paster serve运行的应用提供配置参数。我们安装development.ini中配置段落逐项看一下其具体的作用。
[server:main]
use = egg:Paste#http
host = 0.0.0.0
port = 6543
这一段定义了WSGI服务器的一些基本信息。
use = egg:Paste#http表明使用Paste中的http服务器来为应用提供服务。
host = 0.0.0.0表示任何IP地址都可以访问这个应用
port = 6543表示服务端口是6543
在[server:main]里面还可以配置http服务器线程池等各种参数,具体可以查看PasteDeplay。
[pipeline:main]
pipeline =
egg:WebError#evalerror
MyProject
这也是PasteDeplay中定义的格式。这一段定义了paster serve命令运行的应用(这里是一个管道)。
[app:MyProject]
use = egg:MyProject
reload_templates = true
debug_authorization = false
debug_notfound = false
debug_routematch = false
debug_templates = true
default_locale_name = en
这一段就是本应用的配置参数。注意,这里的名字MyProject与pineline中定义的名字一致。
在本段配置参数中,use = egg:MyProject 这里省略了#main(即use = egg:MyProject#main)。这个定义指明了本应用的入口程序,这里是MyProject这个egg包中的main函数(可以查看myproject目录下的__init__.py文件,里面就定义了这个main函数)。
另外还有reload_templates、debug_templates也需要注意一下,这主要是在开发中调试方便使用的,在应用部署时记得设成false。
development.ini中还有一大段python 标准log信息的配置,都懂得,不解释。
二、production.ini
Pyramid还加了一个产品部署时用的配置文件production.ini,基本等同与development.ini。主要区别是去掉了WebError交互调试界面,以及一些调试开关。
三、MANIFEST.in文件
这是distutils这个打包工具的配置文件(setuptools是distutils的一个扩展)。主要在里面列出了一些需要打进egg包的非python文件。
四、setup.py
这是运行setuptools所需要的启动文件。我们在单元测试、打包、分发等工作时经常需要使用它。这基本已经是python世界里面的事实标准了。
在这个文件里面,我们需要注意的配置项如下:
name=’MyProject’ 项目名,包名
version=’0.0’ 版本,这个经常需要改动
packages=find_packages() 打包时需要打到包中的内容,默认所有
zip_safe=False 指定该包是否能够不解压就能被引用
install_requires=requires, tests_require=requires 指定了本项目的依赖关系,需要什么包才能安装、测试
test_suite="myproject" 指定了单元测试搜索路径
entry_points 定义了本项目的入口。
定义好我们就可以使用
python setup.py sdist
这样的命令将整个项目打包。不同的打包命令及其区别参见setuptools
五、setup.cfg
这个文件是setuptools的参数配置文件,主要配置了单元测试、国际化等方面的一些配置。
[nosetests]
match = ^test
nocapture = 1
cover-package = myproject
with-coverage = 1
cover-erase = 1
这一段是单元测试的配置信息(不过貌似跟python setup.py test命令无关,目前还不清楚在什么地方用到。
其他的信息都是国际化支持的配置,这跟标准python中定义的基本相同。
本文提到的示例材料均源于Pyramid官方网站
Subscribe to:
Posts (Atom)





