python统计字母、空格、数字等字符个数

# -*- coding: utf-8 -*-
# 要求:输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数。
def count(s):
    count_a=count_z=count_o=count_s=0
    for i in s:
        if (ord(i)>=97 and ord(i)<=122) or (ord(i)>=65 and ord(i)<=90):
            count_a=count_a+1
        elif ord(i)>=48 and ord(i)<=57:
            count_z=count_z+1
        elif ord(i)==32:
            count_s=count_s+1
        else:
            count_o=count_o+1
    print "英文字母个数:%d个"%count_a
    print "数字个数:%d个"%count_z
    print "其他字符个数:%d个"%count_o
    print "空格个数:%d个"%count_s


if __name__=="__main__":
    s=raw_input("请输入一串字符:")
    count(s)

运行结果:

请输入一串字符:{“”O: UIK YTJ ET_+(_^@#%@#$^#%*&456587978957FHSJHSRHFDHDFaHSHYWER YWERF R454qggsdhshrths
英文字母个数:48个
数字个数:15个
其他字符个数:22个
空格个数:7个

总结:

ord()将字符转换为ASCII码

python Web开发之 WSGI & uwsgi & uWSGI

未分类

未分类

首先弄清下面几个概念:

WSGI

全称是Web Server Gateway Interface,WSGI不是服务器,python模块,框架,API或者任何软件,只是一种规范,描述web server如何与web application通信的规范。server和application的规范在PEP 3333中有具体描述。要实现WSGI协议,必须同时实现web server和web application,当前运行在WSGI协议之上的web框架有Bottle, Flask, Django。

WSGI是Web 服务器(uWSGI)与 Web 应用程序或应用框架(Django)之间的一种低级别的接口

wsgi server (比如uWSGI) 要和 wsgi application(比如django )交互,uwsgi需要将过来的请求转给django 处理,那么uWSGI 和 django的交互和调用就需要一个统一的规范,这个规范就是WSGI WSGI(Web Server Gateway Interface)

WSGI,全称 Web Server Gateway Interface,或者 Python Web Server Gateway Interface ,是为 Python 语言定义的 Web 服务器和 Web 应用程序或框架之间的一种简单而通用的接口。自从 WSGI 被开发出来以后,许多其它语言中也出现了类似接口。

WSGI 的官方定义是,the Python Web Server Gateway Interface。从名字就可以看出来,这东西是一个Gateway,也就是网关。网关的作用就是在协议之间进行转换。

WSGI 是作为 Web 服务器与 Web 应用程序或应用框架之间的一种低级别的接口,以提升可移植 Web 应用开发的共同点。WSGI 是基于现存的 CGI 标准而设计的。

uwsgi

与WSGI一样是一种通信协议,是uWSGI服务器的独占协议,用于定义传输信息的类型(type of information),每一个uwsgi packet前4byte为传输信息类型的描述,与WSGI协议是两种东西,据说该协议是fcgi协议的10倍快。

uWSGI

是一个web服务器,实现了WSGI协议、uwsgi协议、http协议等。

uWSGI是一个Web服务器,它实现了WSGI协议、uwsgi、http等协议。Nginx中HttpUwsgiModule的作用是与uWSGI服务器进行交换。

WSGI协议主要包括server和application两部分

  • WSGI server负责从客户端接收请求,将request转发给application,将application返回的response返回给客户端;

  • WSGI application接收由server转发的request,处理请求,并将处理结果返回给server。application中可以包括多个栈式的中间件(middlewares),这些中间件需要同时实现server与application,因此可以在WSGI服务器与WSGI应用之间起调节作用:对服务器来说,中间件扮演应用程序,对应用程序来说,中间件扮演服务器。

WSGI协议其实是定义了一种server与application解耦的规范,即可以有多个实现WSGI server的服务器,也可以有多个实现WSGI application的框架,那么就可以选择任意的server和application组合实现自己的web应用。例如uWSGI和Gunicorn都是实现了WSGI server协议的服务器,Django,Flask是实现了WSGI application协议的web框架,可以根据项目实际情况搭配使用。

未分类

像Django,Flask框架都有自己实现的简单的WSGI server,一般用于服务器调试,生产环境下建议用其他WSGI server。

FastCgi协议, uwsgi协议, http协议有什么用?

nginx 和 uWSGI交互就必须使用同一个协议,而上面说了uwsgi支持fastcgi,uwsgi,http协议,这些都是nginx支持的协议,只要大家沟通好使用哪个协议,就可以正常运行了。

uwsgi是服务器和服务端应用程序的通信协议,规定了怎么把请求转发给应用程序和返回

# WSGI和uwsgi
https://www.jianshu.com/p/679dee0a4193
# uWSGI,WSGI和uwsgi
https://www.cnblogs.com/wspblog/p/8575101.html

virtualenv 指定 python 解释器的版本

使用如下命令为 ubuntu 系统安装 virtualenv

sudo apt-get install python-virtualenv

当我们使用 virtualenv 命令创建虚拟环境时,默认使用的 python 解释器为 /usr/bin/python27(然后创建该解释器对应的副本),那么我们该如何指定解释器的版本呢?

使用参数 -p

$ sudo virtualenv -p ~/anaconda3/bin/python test

CentOS 7 安装 Python 3.7

Python 3.7 稳定版已经发布,Python 3.7 具有很多新特性,新用户推荐使用 Python 3.7,本文介绍如何在 CentOS7 系统上安装 Python 3.7,因为 CentOS 7 系统自带的 Python 版本是 Python 2.7。

CentOS 的第三方软件源中(如:IUS,SCL,EPEL)还没有 Python 3.7 的 RPM 软件包,本文先只介绍使用源码方式安装 Python 3.7。

CentOS 7 使用源文件安装 Python 3.7

1)安装依赖包

因为使用源码方式在 CentOS 7 系统中安装 Python 3.7,所以必须安装 GCC 编译器和 make 编译工具,这些软件包包含在 “Development tools” 软件组中,可以直接安装 “Development tools” 软件组:

sudo yum groupinstall "Development tools"

因为 Python 3.7 源文件使用 zlib 格式打包,所以需要安装 zlib 软件包;Python 3.7 编译安装时需要使用 zlib 的头文件和链接库,所以需要安装 zlib 的头文件和链接库 zlib-devel 软件包:

sudo yum -y install zlib zlib-devel

Python 3 有个内置模块 ctypes,它是 Python 3 的外部函数库(Foreign function library),它需要使用系统外部函数库(libffi)的头文件和链接库,所以需要安装外部函数库(libffi)头文件和链接库 libffi-devel 软件包:

sudo yum -y install libffi-devel

2)运行如下命令配置、编译、安装 Python 3.7

wget https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tar.xz
tar xJf Python-3.7.0.tar.xz
cd Python-3.7.0
sudo ./configure
sudo make
sudo make install

如果在编译安装时提示 zipimport.ZipImportError: can’t decompress data; zlib not available 错误,请查看关于 zlib 的解决方法。

如果在编译安装时提示 ModuleNotFoundError: No module named ‘_ctypes’ 错误,请查看关于 ctypes 的解决方法。

3)安装完成后,Python 3.7 安装在了/usr/local文件夹中,可运行文件/usr/local/bin,库文件/usr/local/lib。因为 /usr/local/bin 在 Shell 路径中,所以可以直接在 Shell 中输入如下命令 python3 运行 Python 3.7 解释器。

数据科学20个最好的Python库

Python 在解决数据科学任务和挑战方面继续处于领先地位。去年,我们曾发表一篇博客文章 Top 15 Python Libraries for Data Science in 2017,概述了当时业已证明最有帮助的Python库。今年,我们扩展了这个清单,增加了新的 Python 库,并重新审视了去年已经讨论过的 Python 库,重点关注了这一年来的更新。
我们的选择实际上包含了 20 多个库,因为其中一些库是相互替代的,可以解决相同的问题。因此,我们将它们放在同一个分组。

核心库和统计数据

1. NumPy (Commits: 17911, Contributors: 641)

官网:http://www.numpy.org/

NumPy 是科学应用程序库的主要软件包之一,用于处理大型多维数组和矩阵,它大量的高级数学函数集合和实现方法使得这些对象执行操作成为可能。

2. SciPy (Commits: 19150, Contributors: 608)

官网:https://scipy.org/scipylib/

科学计算的另一个核心库是 SciPy。它基于 NumPy,其功能也因此得到了扩展。SciPy 主数据结构又是一个多维数组,由 Numpy 实现。这个软件包包含了帮助解决线性代数、概率论、积分计算和许多其他任务的工具。此外,SciPy 还封装了许多新的 BLAS 和 LAPACK 函数。

3. Pandas (Commits: 17144, Contributors: 1165)

官网:https://pandas.pydata.org/

Pandas 是一个 Python 库,提供高级的数据结构和各种各样的分析工具。这个软件包的主要特点是能够将相当复杂的数据操作转换为一两个命令。Pandas包含许多用于分组、过滤和组合数据的内置方法,以及时间序列功能。

4. StatsModels (Commits: 10067, Contributors: 153)

官网:http://www.statsmodels.org/devel/

Statsmodels 是一个 Python 模块,它为统计数据分析提供了许多机会,例如统计模型估计、执行统计测试等。在它的帮助下,你可以实现许多机器学习方法并探索不同的绘图可能性。
Python 库不断发展,不断丰富新的机遇。因此,今年出现了时间序列的改进和新的计数模型,即 GeneralizedPoisson、零膨胀模型(zero inflated models)和 NegativeBinomialP,以及新的多元方法:因子分析、多元方差分析以及方差分析中的重复测量。

可视化

5. Matplotlib (Commits: 25747, Contributors: 725)

官网:https://matplotlib.org/index.html

Matplotlib 是一个用于创建二维图和图形的底层库。藉由它的帮助,你可以构建各种不同的图标,从直方图和散点图到费笛卡尔坐标图。此外,有许多流行的绘图库被设计为与matplotlib结合使用。

未分类

6. Seaborn (Commits: 2044, Contributors: 83)

官网:https://seaborn.pydata.org/

Seaborn 本质上是一个基于 matplotlib 库的高级 API。它包含更适合处理图表的默认设置。此外,还有丰富的可视化库,包括一些复杂类型,如时间序列、联合分布图(jointplots)和小提琴图(violin diagrams)。

未分类

7. Plotly (Commits: 2906, Contributors: 48)

官网:https://plot.ly/python/

Plotly 是一个流行的库,它可以让你轻松构建复杂的图形。该软件包适用于交互式 Web 应用程,可实现轮廓图、三元图和三维图等视觉效果。

8. Bokeh (Commits: 16983, Contributors: 294)

官网:https://bokeh.pydata.org/en/latest/
Bokeh 库使用 JavaScript 小部件在浏览器中创建交互式和可缩放的可视化。该库提供了多种图表集合,样式可能性(styling possibilities),链接图、添加小部件和定义回调等形式的交互能力,以及许多更有用的特性。

未分类

9. Pydot (Commits: 169, Contributors: 12)

官网:https://pypi.org/project/pydot/

Pydot 是一个用于生成复杂的定向图和无向图的库。它是用纯 Python 编写的Graphviz 接口。在它的帮助下,可以显示图形的结构,这在构建神经网络和基于决策树的算法时经常用到。

未分类

机器学习

10. Scikit-learn (Commits: 22753, Contributors: 1084)

官网:http://scikit-learn.org/stable/

这个基于 NumPy 和 SciPy 的 Python 模块是处理数据的最佳库之一。它为许多标准的机器学习和数据挖掘任务提供算法,如聚类、回归、分类、降维和模型选择。

利用 Data Science School 提高你的技能

Data Science School:http://datascience-school.com/

11. XGBoost / LightGBM / CatBoost (Commits: 3277 / 1083 / 1509, Contributors: 280 / 79 / 61)

官网:http://xgboost.readthedocs.io/en/latest/http://lightgbm.readthedocs.io/en/latest/Python-Intro.htmlhttps://github.com/catboost/catboost

梯度增强算法是最流行的机器学习算法之一,它是建立一个不断改进的基本模型,即决策树。因此,为了快速、方便地实现这个方法而设计了专门库。就是说,我们认为 XGBoost、LightGBM 和 CatBoost 值得特别关注。它们都是解决常见问题的竞争者,并且使用方式几乎相同。这些库提供了高度优化的、可扩展的、快速的梯度增强实现,这使得它们在数据科学家和 Kaggle 竞争对手中非常流行,因为在这些算法的帮助下赢得了许多比赛。

12. Eli5 (Commits: 922, Contributors: 6)

官网:https://eli5.readthedocs.io/en/latest/

通常情况下,机器学习模型预测的结果并不完全清楚,这正是 Eli5 帮助应对的挑战。它是一个用于可视化和调试机器学习模型并逐步跟踪算法工作的软件包,为 scikit-learn、XGBoost、LightGBM、lightning 和 sklearn-crfsuite 库提供支持,并为每个库执行不同的任务。

深度学习

13. TensorFlow (Commits: 33339, Contributors: 1469)

官网:https://www.tensorflow.org/

TensorFlow 是一个流行的深度学习和机器学习框架,由 Google Brain 开发。它提供了使用具有多个数据集的人工神经网络的能力。在最流行的 TensorFlow应用中有目标识别、语音识别等。在常规的 TensorFlow 上也有不同的 leyer-helper,如 tflearn、tf-slim、skflow 等。

14. PyTorch (Commits: 11306, Contributors: 635)

官网:https://pytorch.org/

PyTorch 是一个大型框架,它允许使用 GPU 加速执行张量计算,创建动态计算图并自动计算梯度。在此之上,PyTorch 为解决与神经网络相关的应用程序提供了丰富的 API。该库基于 Torch,是用 C 实现的开源深度学习库。

15. Keras (Commits: 4539, Contributors: 671)

官网:https://keras.io/

Keras 是一个用于处理神经网络的高级库,运行在 TensorFlow、Theano 之上,现在由于新版本的发布,还可以使用 CNTK 和 MxNet 作为后端。它简化了许多特定的任务,并且大大减少了单调代码的数量。然而,它可能不适合某些复杂的任务。

分布式深度学习

16. Dist-keras / elephas / spark-deep-learning (Commits: 1125 / 170 / 67, Contributors: 5 / 13 / 11)

官网:http://joerihermans.com/work/distributed-
keras/https://pypi.org/project/elephas/https://databricks.github.io/spark-deep-learning/site/index.html

随着越来越多的用例需要花费大量的精力和时间,深度学习问题变得越来越重要。然而,使用像 Apache Spark 这样的分布式计算系统,处理如此多的数据要容易得多,这再次扩展了深入学习的可能性。因此,dist-keras、elephas 和 spark-deep-learning 都在迅速流行和发展,而且很难挑出一个库,因为它们都是为解决共同的任务而设计的。这些包允许你在 Apache Spark 的帮助下直接训练基于 Keras 库的神经网络。Spark-deep-learning 还提供了使用 Python 神经网络创建管道的工具。

自然语言处理

17. NLTK (Commits: 13041, Contributors: 236)

官网:https://www.nltk.org/

NLTK 是一组库,一个用于自然语言处理的完整平台。在 NLTK 的帮助下,你可以以各种方式处理和分析文本,对文本进行标记和标记,提取信息等。NLTK 也用于原型设计和建立研究系统。

18. SpaCy (Commits: 8623, Contributors: 215)

官网:https://spacy.io/

SpaCy 是一个具有优秀示例、API 文档和演示应用程序的自然语言处理库。这个库是用 Cython 语言编写的,Cython 是 Python 的 C 扩展。它支持近 30 种语言,提供了简单的深度学习集成,保证了健壮性和高准确率。SpaCy 的另一个重要特性是专为整个文档处理设计的体系结构,无须将文档分解成短语。

19. Gensim (Commits: 3603, Contributors: 273)

官网:https://radimrehurek.com/gensim/

Gensim 是一个用于健壮语义分析、主题建模和向量空间建模的 Python 库,构建在Numpy和Scipy之上。它提供了流行的NLP算法的实现,如 word2vec。尽管 gensim 有自己的 models.wrappers.fasttext实现,但 fasttext 库也可以用来高效学习词语表示。

数据采集

20. Scrapy (Commits: 6625, Contributors: 281)

官网:https://scrapy.org/

Scrapy 是一个用来创建网络爬虫,扫描网页和收集结构化数据的库。此外,Scrapy 可以从 API 中提取数据。由于该库的可扩展性和可移植性,使得它用起来非常方便。

结论

本文上述所列就是我们在 2018 年为数据科学领域中丰富的 Python 库集合。与上一年相比,一些新的现代库越来越受欢迎,而那些已经成为经典的数据科学任务的库也在不断改进。

下表显示了 GitHub 活动的详细统计数据:

未分类

python的BaseHTTPServer模块接收post请求

#!/usr/bin/python
#encoding=utf-8
'''
基于BaseHTTPServer的http server实现,包括get,post方法,get参数接收,post参数接收。
'''
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import io,shutil  
import urllib
import os, sys

class MyRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        mpath,margs=urllib.splitquery(self.path) # ?分割
        self.do_action(mpath, margs)

    def do_POST(self):
        mpath,margs=urllib.splitquery(self.path)
        datas = self.rfile.read(int(self.headers['content-length']))
        self.do_action(mpath, datas)

    def do_action(self, path, args):
            self.outputtxt(path + args )

    def outputtxt(self, content):
        #指定返回编码
        enc = "UTF-8"
        content = content.encode(enc)          
        f = io.BytesIO()
        f.write(content)
        f.seek(0)  
        self.send_response(200)  
        self.send_header("Content-type", "text/html; charset=%s" % enc)  
        self.send_header("Content-Length", str(len(content)))  
        self.end_headers()  
        shutil.copyfileobj(f,self.wfile)

Python-Jenkins API使用 —— 在后端代码中操控Jenkins

最近在工作中需要用到在后台代码中触发Jenkins任务的构建,于是想到Jenkins是否有一些已经封装好的API类库提供,用于处理跟Jenkins相关的操作。下面就简单介绍下我的发现。

Linux Curl

  
首先找到的是Jenkins官网的wiki:https://wiki.jenkins-ci.org/display/JENKINS/Remote+access+API

在官网首页就有关于触发job的方法:

未分类

个人尝试了下,该方式是通过命令行直接调curl去发POST请求的方式来触发job的构建。对于用openid管理的Jenkins,需要带上参数–user USER:PASSWORD,其中的USER和PASSWORD不是你的openID登录的账号密码,而是登录后显示在Jenkins中的User Id和API Token,它们的的查看方式如下:

用openID登录jenkins —> 点击右上角的用户名,进入用户个人页面 —> 点击左边的设置,打开设置页面 —> API Token,Show Api Token…

如果需要参数化构建job,则要加上–data-urlencode json='{“parameter”: [{“name”:”param_name1″,”value”:”param_value1″}, {“name”:”param_name2″,”value”:”param_value2″}]}’

显然,这种方式比较繁琐,很容易出现因格式不正确导致触发任务失败,而且这种方式不能帮助我们获取更多的关于job的信息以便于我们后续对job的状态进行跟踪。

Python-Jenkins

  
继续寻找,然后我在Jenkins官网上找到了Python-Jenkins API,仔细阅读后发现,它几乎涵盖了大部分Jenkins的操作,大大方便了我们在后台进行对Jenkins的一些列操作。

Python-Jenkins官网:https://pypi.python.org/pypi/python-jenkins/

Python-Jenkins Doc:http://python-jenkins.readthedocs.io/en/latest/index.html

下面简单介绍下如何使用Python-Jenkins:

1.安装

   sudo pip install python-jenkins

  
2.进入python命令环境或创建新的.py文件jenkinsApiTest.py

   import jenkins

     #定义远程的jenkins master server的url,以及port

     jenkins_server_url='xxxx:xxxx'

     #定义用户的User Id 和 API Token,获取方式同上文

     user_id='xxxx'

     api_token='xxxx'

   #实例化jenkins对象,连接远程的jenkins master server

   server=jenkins.Jenkins(jenkins_server_url, username=user_id, password=api_token)

   #构建job名为job_name的job(不带构建参数)

   server.build_job(job_name)

   #String参数化构建job名为job_name的job, 参数param_dict为字典形式,如:param_dict= {"param1":“value1”, “param2”:“value2”} 

   server.build_job(job_name, parameters=param_dict)

   #获取job名为job_name的job的相关信息

   server.get_job_info(job_name)

   #获取job名为job_name的job的最后次构建号

   server.get_job_info(job_name)['lastBuild']['number']

     #获取job名为job_name的job的某次构建的执行结果状态

   server.get_build_info(job_name,build_number)['result']     

     #判断job名为job_name的job的某次构建是否还在构建中

   server.get_build_info(job_name,build_number)['building']

3.更多其他的API可以参考Python-Jenkins API:http://python-jenkins.readthedocs.io/en/latest/api.html

Python3 Flask+nginx+Gunicorn部署(下)

继续上一篇文章,在上一篇文章中,我们已经把gunicorn和nginx运行并且安装好了,在这一篇,我们需要进行nginx与gunicorn端口进行绑定

上一篇,我们已经将gunicorn运行起来了

gunicorn -w 4 -b 127.0.0.1:8000 入口文件名:app

nginx操作目录:

/usr/local/nginx/sbin

在/usr/local/nginx/sbin目录下可以进行nginx的重启、重载、停止与启动。

在这里我们进行通过nginx反向代理网站域名与服务器,这里可能说得有些绕口,

通俗点:
就是别人访问我们的网站,是通过nginx反向代理再把访问请求发送到flask服务器上的。

首先我们设置一下nginx的配置文件

cd /usr/local/nginx/conf
vi nginx.conf

然后打开配置文件:

    #gzip  on;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    server {
        listen       80;
        server_name  www.00reso.com;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
           # root   html;
           # index  index.html index.htm;
            proxy_pass http://127.0.0.1:8000;
            access_log /home/admin/api_access.log;
            proxy_read_timeout 60;
            error_log  /home/admin/api_error.log;
        }

主要动的地方:

#gzip  on;
# 1代理的设置吧,这个都是这样设置的
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

# 2绑定的域名
server_name  www.00reso.com;

# 3 监听本服务器的端口,设置log,请求时间等
proxy_pass http://127.0.0.1:8000;
            access_log /home/admin/api_access.log;
            proxy_read_timeout 60;
            error_log  /home/admin/api_error.log;

然后进行保存。

接下来重载一下nginx文件,在/usr/local/nginx/sbin/nginx下
使用命令:

sudo nginx -t

如果看到

1 nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
2 nginx: configuration file /etc/nginx/nginx.conf test is successful

就是代表成功了。

重新启动下nginx

sudo service nginx restart

这里重启nginx的命令可能会行不通,这时候,你用
ps -e aux|grep nginx 把nginx的进程杀掉,

然后在 /usr/local/nginx/sbin目录下再次启动nginx

nginx

如果看到:

[admin@izbp11722iq94py8qx691sz conf]$ ps -e aux|grep nginx
root      2657  0.0  0.0  24952   784 ?        Ss   Jun25   0:00 nginx: master process nginx
nobody    2658  0.0  0.1  25388  1752 ?        S    Jun25   0:00 nginx: worker process
admin    13814  0.0  0.0 112664   968 pts/2    S+   20:59   0:00 grep --color=auto nginx

这个情况,就是启动nginx成功了,

验证

1 使用本地ping

curl localhost:80

如果出现flask index页面的内容,就表示nginx与gunicorn配置成功,
2 远程直接输入www.00reso.com 看是否能进行访问,如果没有出现失败的页面,则访问成功,如果出现失败的页面,则大多是防火墙或80端口关闭了,这里我们需要把防火墙打开。

编辑防火墙白名单

[root@localhost ~]# vim /etc/sysconfig/iptables
增加下面一行代码
-A INPUT -p tcp -m state -- state NEW -m tcp --dport 80 -j ACCEPT
保存退出,重启防火墙
[root@localhost ~]# service iptables restart

未分类

这样就可以进行访问了

目前自己还在探索中,现在在快马加鞭的优化中,

因为flask+nginx+gunicorn部署自己踩过了很多坑,但是从坑中踩过来,差不多就都懂了。还好没放弃~~

Python Web 腾讯云部署:flask+fabric+gunicorn+nginx+supervisor

最近看了《Flask Web开发–基于Python的Web应用开发实战》,还有廖雪峰老师的Python教程,前者是基于Web框架flask进行开发,后者是自己搭建了一个Web框架。Web框架致力于如何生成HTML代码,而Web服务器用于处理和响应HTTP请求。Web框架和Web服务器之间的通信,需要一套双方都遵守的接口协议。WSGI协议就是用来统一这两者的接口的。

为了部署一个完整的环境,本文将使用flask作为Web框架,Gunicorn作为WSGI容器,Nginx作为Web服务器,同时使用Supervisor进行进程管理,并使用Fabric实现自动化部署。

前期准备

申请一个腾讯云服务器Ubuntu Server 16.04.1 LTS 64位:

账户:ubuntu
密码:**********
内网ip:172.16.0.17
外网ip:139.199.184.183

使用《Flask Web开发》源码:

$ mkdir web
$ cd web
~/web$ git clone https://github.com/miguelgrinberg/flasky.git

设置并进入虚拟环境:

~/web$ cd flasky
~/web/flasky$ virtualenv venv
~/web/flasky$ source venv/bin/activate

安装对应的库:

(venv) ~/web/flasky$ cd requirements
(venv) ~/flasky/requirements$ pip3 install -r common.txt
(venv) ~/flasky/requirements$ pip3 install -r dev.txt
(venv) ~/flasky/requirements$ pip3 install -r heroku.txt
(venv) ~/flasky/requirements$ pip3 install -r prod.txt

创建数据库:

(venv) ~/flasky/requirements$ cd ..
(venv) ~/flasky/$ python3 manage.py deploy

Fabric

Fabric入门看这里https://www.jianshu.com/p/0be28f6c4607

新开一个终端,远程登陆服务器:

$ ssh [email protected]

在服务器端定义好部署结构:

ubuntu@VM $ mkdir web
ubuntu@VM $ mkdir web/flasky
ubuntu@VM $ mkdir web/log

即:

  • web/    Web App根目录
    • flasky/  存放python文件
    • log/    存放日志文件

我们使用Fabric将代码上传到服务器,首先,安装Fabric:

(venv) ~/web$ sudo apt-get install fabric

在web目录下创建fabfile.py(必须这个名字),写入:

#!/usr/bin/python3
# -*- coding: utf-8 -*-
import os, re
from datetime import datetime

# 导入Fabric API:
from fabric.api import *

# 服务器登录用户名:
env.user = 'ubuntu'
# sudo用户为root:
env.sudo_user = 'root'
# 服务器地址,可以有多个,依次部署:
env.hosts = ['139.199.184.183']

_TAR_FILE = 'dist-flasky.tar.gz'

def build():
    includes = ['app', 'migrations', 'requirements', 'tests', 'venv', *.py', '*.sqlite']
    excludes = ['.*', '*.pyc', '*.pyo']
    local('rm -f dist/%s' % _TAR_FILE)
    with lcd(os.path.join(os.path.abspath('.'), 'flasky')):
        cmd = ['tar', '--dereference', '-czvf', '../dist/%s' % _TAR_FILE]
        cmd.extend(['--exclude='%s'' % ex for ex in excludes])
        cmd.extend(includes)
        local(' '.join(cmd))


_REMOTE_TMP_TAR = '/tmp/%s' % _TAR_FILE
_REMOTE_BASE_DIR = '/home/ubuntu/web/flasky'

def deploy():
    newdir = 'flask-%s' % datetime.now().strftime('%y-%m-%d_%H.%M.%S')
    # 删除已有的tar文件:
    run('rm -f %s' % _REMOTE_TMP_TAR)
    # 上传新的tar文件:
    put('dist/%s' % _TAR_FILE, _REMOTE_TMP_TAR)
    # 创建新目录:
    with cd(_REMOTE_BASE_DIR):
        sudo('mkdir %s' % newdir)
    # 解压到新目录:
    with cd('%s/%s' % (_REMOTE_BASE_DIR, newdir)):
        sudo('tar -xzvf %s' % _REMOTE_TMP_TAR)
    # 重置软链接:
    with cd(_REMOTE_BASE_DIR):
        sudo('rm -f flask')
        sudo('ln -s %s flask' % newdir)
        sudo('chown ubuntu:ubuntu flask')
        sudo('chown -R ubuntu:ubuntu %s' % newdir)
    # 重启Python服务和nginx服务器:
    #with settings(warn_only=True):
    #    sudo('supervisorctl stop flask')
    #    sudo('supervisorctl start flask')
    #    sudo('/etc/init.d/nginx reload')

使用fab命令将代码打包:

(venv) ~/web$ mkdir dist
(venv) ~/web$ fab build

将代码传上服务器:

(venv) ~/web$ fab deploy

Gunicorn部署

gunicorn入门看这里https://www.jianshu.com/p/260f18aa5462

代码上传给服务器后,可以直接运行manage.py文件,就可以访问网站了。可是实际情景中需要处理高并发访问的情况,我们使用Gunicorn来解决这个问题。

在服务器上进入flask所在目录,激活虚拟环境,并安装gunicorn:

ubuntu@VM ~/web/flasky/flask$ source venv/bin/activate
(venv) ubuntu@VM ~/web/flasky/flask$  sudo apt-get install gunicorn

使用gunicorn运行web应用(支持4个并发请求):

(venv) ubuntu@VM ~/web/flasky/flask$ gunicorn -w 4 -b 172.16.0.17:5000 manage:app

其中172.16.0.17是服务器内网ip,这样设置后就可以通过外网ip访问网站了。在浏览器地址栏中输入139.199.184.183:5000,就可以看到网站了。

Nginx

Nginx入门看这里

使用gunicorn的话,需要将端口暴露给外界,这不利于服务器的安全问题。Nginx是一个高性能的HTTP和反向代理服务器,通过配置一个代理服务器,可以实现反向代理的功能。所谓反向代理,是指一个请求,从互联网过来,先进入代理服务器,再由代理服务器转发给局域网的目标服务器。

先安装nginx:

(venv) ubuntu@VM ~$ sudo apt-get install nginx

设置反向代理服务器:在服务器,进入目录/etc/nginx/sites-available/,在目录下的default文件写入一个server。

首先,先备份default文件:

$ cd /etc/nginx/sites-available/
$ sudo cp default default-backup

在default文件中写入server:

server {
    listen 80;
    root /home/ubuntu/web/flasky/flask/;

    location / {
        proxy_pass http://127.0.0.1:5000;
        proxy_set_header Host $host;
        proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
    }
}

配置完成后,重启nginx:

$ sudo nginx -s reload

此时,该反向代理服务器就开始监听80端口。80端口是为HTTP开放的端口,浏览网页服务默认的端口号都是80 (8080端口跟80端口一样)。只要访问服务器,代理服务器就会将请求转发到127.0.0.1:5000.

回到目录/home/ubuntu/web/flasky/flask/下,再次使用gunicorn运行web app:

(venv) ubuntu@VM ~/web/flasky/flask$ gunicorn -w 4 -b 127.0.0.1:5000 manage:app

用的ip地址是127.0.0.1

而外界要访问网站只需要在浏览器地址栏输入139.199.184.183,使用默认端口80。这样web app实际使用的5000就不用暴露了。

Supervisor

supervisor入门看这里https://www.jianshu.com/p/0226b7c59ae2

如果你需要进程一直执行,若该进程因各种原因中断,也会自动重启的话,supervisor是一个很好的选择。

supervisor管理进程,是通过fork/exec的方式将这些被管理的进程当作supervisor的子进程来启动,所以我们只需要将要管理进程的可执行文件的路径添加到supervisor的配置文件中就好了。此时被管理进程被视为supervisor的子进程,若该子进程异常终端,则父进程可以准确的获取子进程异常终端的信息,通过在配置文件中设置autostart=true,可以实现对异常中断的子进程的自动重启。

安装supervisor:

(venv) ubuntu@VM ~$ sudo apt-get install supervisor

在目录/etc/supervisor/conf.d/下创建flask.conf,并加入:

;/etc/supervisor/conf.d/flask.conf

[program:flask]

command     = /home/ubuntu/.local/bin/gunicorn -w 4 -b 127.0.0.1:5000 manage:app
;这里/home/ubuntu/.local/bin/是我服务器上gunicorn的安装目录
directory   = /home/ubuntu/web/flasky/flask
user        = ubuntu
startsecs   = 3
autostart   = true

redirect_stderr         = true
stdout_logfile_maxbytes = 50MB
stdout_logfile_backups  = 10
stdout_logfile          = /home/ubuntu/web/flasky/log/app.log

配置完后,进入目录/home/ubuntu/web/flasky/, 创建log目录:

(venv) ubuntu@VM ~/web/flasky$ mkdir log

启动supervisor:

(venv) ubuntu@VM /etc/supervisor$ sudo supervisord -c supervisor.conf                 

执行服务(运行app.py):

(venv) ubuntu@VM $ sudo supervisorctl start flask

此时,进程flask运行,执行command后边的语句,即/home/ubuntu/.local/bin/gunicorn -w 4 -b 127.0.0.1:5000 manage:app。

在浏览器地址栏输入139.199.184.183,使用默认端口80,即可访问网站。

如果supervisor遇到错误,可以在/var/log/supervisor/supervisord.log中查看日志;
如果app运行出现问题,可以在 /home/ubuntu/web/flasky/log/app.log中查看日志。

自动化部署

为了实现自动化部署,将上边fabfile.py文件的最后四个语句的注释取消,就能在将修改后的代码传上服务器后,用supervisor自动重载配置并重启flask进程。之后便可以直接访问网站。
因此,每次更改代码后,只需要执行以下两个语句,无需登陆服务器,便可以启动网站:

$ fab build
$ fab deploy

gunicorn配置文件

gunicorn的配置除了可以在命令行中设置,也可以使用配置文件实现更复杂的配置:

$ gunicorn -c gunicorn.py manage:app

gunicorn.py文件如下:

# gunicorn.py
import logging
import logging.handlers
from logging.handlers import WatchedFileHandler
import os
import multiprocessing
bind = '127.0.0.1:5000'       #绑定ip和端口号
backlog = 512                 #监听队列
chdir = '/home/test/server/bin'   #gunicorn要切换到的目的工作目录
timeout = 30      #超时
worker_class = 'gevent' #使用gevent模式,还可以使用sync 模式,默认的是sync模式
workers = multiprocessing.cpu_count() * 2 + 1    #进程数

threads = 2 #指定每个进程开启的线程数

loglevel = 'info' #日志级别,这个日志级别指的是错误日志的级别,而访问日志的级别无法设置
access_log_format = '%(t)s %(p)s %(h)s "%(r)s" %(s)s %(L)s %(b)s %(f)s" "%(a)s"'     #设置gunicorn访问日志格式,错误日志无法设置
"""
其每个选项的含义如下
        h           remote address
        l           '-'
        u           currently '-', may be user name in future releases
        t           date of the request
        r           status line (e.g. ``GET / HTTP/1.1``)
        s           status
        b           response length or '-'
        f           referer
        a           user agent
        T           request time in seconds
        D           request time in microseconds
        L           request time in decimal seconds
        p           process ID
        {Header}i   request header
        {Header}o   response header
"""
accesslog = "/home/ubutnu/web/flasky/log/gunicorn_access.log"      #访问日志文件
errorlog = "/home/ubutnu/web/flasky/log/gunicorn_error.log"        #错误日志文件

在本地将gunicorn.py放在/home/ubutnu/web/flasky/flask/目录下,在服务器端将/etc/supervisor/conf.d/flask.conf中的command改为:

command     = /home/ubuntu/.local/bin/gunicorn -c /home/ubutnu/web/flasky/flask/gunicorn.py manage:app

然后,在本地执行:

$ fab build
$ fab deploy

便可以访问网站了。

未分类

python的加、减、乘、除、取整、取余计算

注意:所用版本是Python3.5.2。(因为Python2系列和Python3系列差距很大,特别提醒)

加法:

输入以下代码:

>>>1+1
>>>1.0+1

减法:

输入以下代码:

>>>1-2
>>>1.0-2

乘法:

输入以下代码:

>>>2*4
>>>2.0*4

除法:

输入以下代码:

>>>2/4
>>>2.0/4
>>>2//4
>>>2.0//4

取整:

输入以下代码:

>>>2//4
>>>2.0//4
>>>2.01//4

取余:

输入以下代码:

>>>10%2
>>>10%2.0

现象:

未分类