英文原文文档可参考 https://devcenter.heroku.com/articles/getting-started-with-python-o
今天Heroku宣布支持Python,原本一直眼馋Ruby的同学有Heroku这个云主机平台,终于等到支持Python,立刻尝鲜一把。
安装Heroku环境
虽然系统是Ubuntu 10.04,但因为不想增加apt-get-repository,我没有使用官方推荐的apt-get方式。采用tarball方式,下载解压运行,提示没有ruby环境,那就安装吧:
sudo apt-get install ruby rubygems libreadline-ruby libopenssl-ruby
然后手动把解压出来的heroku-client文件夹加到PATH路径里。
配置Heroku环境
此处借用Heroku的文档,配置Heroku登录凭据与公私钥
$ heroku login
Enter your Heroku credentials.
Email: adam@example.com
Password:
Could not find an existing public key.
Would you like to generate one? [Yn]
Generating new SSH public key.
Uploading ssh public key /Users/adam/.ssh/id_rsa.pub
编写hello world
Heroku文档是介绍使用flask这个web框架,由于习惯使用web.py,所以使用web.py来编写hello world。
编写pip的requirements.txt
$ echo "web.py==0.36" > requirements.txt
创建一个virtualenv
$ virtualenv --no-site-packages .
New python executable in ./bin/python
Installing setuptools............done.
$source bin/activate
这里的activate很重要,在windows下是打Scripts\activate
然后根据requirements.txt安装环境:
$ bin/pip install -r requirements.txt
Downloading/unpacking web.py==0.36 (from -r requirements.txt (line 1))
Downloading web.py-0.36.tar.gz (87Kb): 87Kb downloaded
Running setup.py egg_info for package web.py
Installing collected packages: web.py
Running setup.py install for web.py
Successfully installed web.py
Cleaning up...
编写.gitignore,将以下内容写到.gitignore文件里
bin
build
include
lib
.Python
*.pyc
编写web.py程序
终于开始写干活的程序,直接上代码:
$ vi hello.py
import web
import os, sys
urls = (
'/(.*)', 'hello'
)
app = web.application(urls, globals())
class hello:
def GET(self, name):
if not name:
name = 'World'
return 'Hello, ' + name + '!'
if __name__ == "__main__":
port = os.environ.get("PORT", "5000")
sys.argv[1] = port
app.run()
由于Heroku会提供PORT环境变量来指定应用程序的端口,而web.py默认使用命令行第一个参数作为端口,因此直接获取环境变量PORT,放到sys.argv[1]里,注意web.py从命令行参数读端口参数,端口参数是字符串。
使用Foreman作为启动脚本
Heroku是ruby系的产品,使用Foreman作为启动脚本
使用rubygems即可安装foreman
$ gem install foreman
在ubuntu 10.04上安装foreman,会遇到错误:
ERROR: Error installing foreman:
thor requires RubyGems version >= 1.3.6
而ubuntu 10.04的默认源里的rubygems是1.3.5的,参考stackoverflow一篇文章,找到解决方法:
sudo gem install rubygems-update
cd /var/lib/gems/1.8/bin
sudo ./update_rubygems
然后编写Procfile,这个Procfile是Foreman所读取的启动项
echo "web: python hello.py 5000" > Procfile
然后就可以启动来看下
$ foreman start
13:20:59 web.1 | started with pid 25656
13:21:00 web.1 | http://0.0.0.0:5000/
正常。
部署到Heroku
Heroku使用git push的部署方式,当代码push到远端,Heroku会自动更新代码并重启应用,使用过git的同学应该不会陌生。
$ heroku create --stack cedar
Creating simple-mountain-9034... done, stack is cedar
http://simple-mountain-9034.herokuapp.com/ | git@heroku.com:simple-mountain-9034.git
Git remote heroku added
然后推送到远端:
$ git push heroku master
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (6/6), 592 bytes, done.
Total 6 (delta 0), reused 0 (delta 0)
-----> Heroku receiving push
-----> Python app detected
-----> Preparing virtualenv version 1.6.1
New python executable in ./bin/python2.7
Also creating executable in ./bin/python
Installing setuptools............done.
Installing pip...............done.
-----> Installing dependencies using pip version 1.0.1
Downloading/unpacking web.py==0.36 (from -r requirements.txt (line 1))
Creating supposed download cache at /app/tmp/repo.git/.cache/pip_downloads
Storing download in cache at /app/tmp/repo.git/.cache/pip_downloads/http%3A%2F%2Fpypi.python.org%2Fpackages%2Fsource%2Fw%2Fweb.py%2Fweb.py-0.36.tar.gz
Running setup.py egg_info for package web.py
Installing collected packages: web.py
Running setup.py install for web.py
Successfully installed web.py
Cleaning up...
-----> Discovering process types
Procfile declares types -> web
-----> Compiled slug size is 2.6MB
-----> Launching... done, v3
http://simple-mountain-9034.herokuapp.com deployed to Heroku
To git@heroku.com:simple-mountain-9034.git
* [new branch] master -> master
这里注意要修改web的进程数:
$ heroku scale web=1
Scaling web processes... done, now running 1
然后可以查看进程的状态:
$ heroku ps
Process State Command
------------ ------------------ ------------------------------
web.1 up for 5s python hello.py 5000