python(sqlalchemy基本使用)

下面就开始让你见证orm的nb之处,盘古开天劈地之前,我们创建一个表是这样的

CREATE TABLE user (
    id INTEGER NOT NULL AUTO_INCREMENT,
    name VARCHAR(32),
    password VARCHAR(64),
    PRIMARY KEY (id)
)

这只是最简单的sql表,如果再加上外键关联什么的,一般程序员的脑容量是记不住那些sql语句的,于是有了orm,实现上面同样的功能,代码如下

import sqlalchemy
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String
engine = create_engine("mysql+pymysql://root:alex3714@localhost/testdb",
                                    encoding='utf-8', echo=True)
Base = declarative_base() #生成orm基类
class User(Base):
    __tablename__ = 'user' #表名
    id = Column(Integer, primary_key=True)
    name = Column(String(32))
    password = Column(String(64))
Base.metadata.create_all(engine) #创建表结构

你说,娘那个腚的,并没有感觉代码量变少啊,呵呵, 孩子莫猴急,好戏在后面

Lazy Connecting
The Engine, when first returned by create_engine(), has not actually tried to connect to the database yet; that happens only the first time it is asked to perform a task against the database.

除上面的创建之外,还有一种创建表的方式,虽不常用,但还是看看吧

http://www.cnblogs.com/alex3714/articles/5978329.html#

事实上,我们用第一种方式创建的表就是基于第2种方式的再封装。

最基本的表我们创建好了,那我们开始用orm创建一条数据试试

Session_class = sessionmaker(bind=engine) #创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例
Session = Session_class() #生成session实例
user_obj = User(name="alex",password="alex3714") #生成你要创建的数据对象
print(user_obj.name,user_obj.id)  #此时还没创建对象呢,不信你打印一下id发现还是None
Session.add(user_obj) #把要创建的数据对象添加到这个session里, 一会统一创建
print(user_obj.name,user_obj.id) #此时也依然还没创建
Session.commit() #现此才统一提交,创建数据

我擦,写这么多代码才创建一条数据,你表示太tm的费劲了,正要转身离开,我拉住你的手不放开,高潮还没到。。

查询

my_user = Session.query(User).filter_by(name="alex").first()
print(my_user)

此时你看到的输出是这样的应该

<__main__.User object at 0x105b4ba90>

我擦,这是什么?这就是你要的数据呀, 只不过sqlalchemy帮你把返回的数据映射成一个对象啦,这样你调用每个字段就可以跟调用对象属性一样啦,like this..

print(my_user.id,my_user.name,my_user.password)
输出
1 alex alex3714

不过刚才上面的显示的内存对象对址你是没办法分清返回的是什么数据的,除非打印具体字段看一下,如果想让它变的可读,只需在定义表的类下面加上这样的代码

def __repr__(self):
    return "<User(name='%s',  password='%s')>" % (
        self.name, self.password)

修改

my_user = Session.query(User).filter_by(name="alex").first()
my_user.name = "Alex Li"
Session.commit()

回滚

my_user = Session.query(User).filter_by(id=1).first()
my_user.name = "Jack"
fake_user = User(name='Rain', password='12345')
Session.add(fake_user)
print(Session.query(User).filter(User.name.in_(['Jack','rain'])).all() )  #这时看session里有你刚添加和修改的数据
Session.rollback() #此时你rollback一下
print(Session.query(User).filter(User.name.in_(['Jack','rain'])).all() ) #再查就发现刚才添加的数据没有了。
# Session
# Session.commit()

获取所有数据

print(Session.query(User.name,User.id).all() )

多条件查询

objs = Session.query(User).filter(User.id>0).filter(User.id<7).all()

上面2个filter的关系相当于 user.id >1 AND user.id <7 的效果

统计和分组

Session.query(User).filter(User.name.like("Ra%")).count()

分组

from sqlalchemy import func
print(Session.query(func.count(User.name),User.name).group_by(User.name).all() )

相当于原生sql为

http://www.cnblogs.com/alex3714/articles/5978329.html#

输出为

[(1, ‘Jack’), (2, ‘Rain’)]

外键关联

我们创建一个addresses表,跟user表关联

from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship
class Address(Base):
    __tablename__ = 'addresses'
    id = Column(Integer, primary_key=True)
    email_address = Column(String(32), nullable=False)
    user_id = Column(Integer, ForeignKey('user.id'))
    user = relationship("User", backref="addresses") #这个nb,允许你在user表里通过backref字段反向查出所有它在addresses表里的关联项
    def __repr__(self):
        return "<Address(email_address='%s')>" % self.email_address
The relationship.back_populates parameter is a newer version of a very common SQLAlchemy feature calledrelationship.backref. The relationship.backref parameter hasn’t gone anywhere and will always remain available! The relationship.back_populates is the same thing, except a little more verbose and easier to manipulate. For an overview of the entire topic, see the section Linking Relationships with Backref.

表创建好后,我们可以这样反查试试

obj = Session.query(User).first()
for i in obj.addresses: #通过user对象反查关联的addresses记录
    print(i)
addr_obj = Session.query(Address).first()
print(addr_obj.user.name)  #在addr_obj里直接查关联的user表

创建关联对象

obj = Session.query(User).filter(User.name=='rain').all()[0]
print(obj.addresses)
obj.addresses = [Address(email_address="[email protected]"), #添加关联对象
                 Address(email_address="[email protected]")]
Session.commit()

常用查询语法

Common Filter Operators

Here’s a rundown of some of the most common operators used in filter():

  • equals:
     query.filter(User.name == 'ed')
  • not equals:
     query.filter(User.name != 'ed')
  • LIKE:

query.filter(User.name.like(‘%ed%’))

  • IN:
  • NOT IN:
    query.filter(~User.name.in_([‘ed’, ‘wendy’, ‘jack’]))
  • IS NULL:
  • IS NOT NULL:
  • AND:
    2.1. ObjectRelationalTutorial 17
query.filter(User.name.in_(['ed', 'wendy', 'jack']))
# works with query objects too:

query.filter(User.name.in_( session.query(User.name).filter(User.name.like(‘%ed%’))

))

query.filter(User.name == None)
# alternatively, if pep8/linters are a concern
query.filter(User.name.is_(None))
query.filter(User.name != None)
# alternatively, if pep8/linters are a concern
query.filter(User.name.isnot(None))

SQLAlchemy Documentation, Release 1.1.0b1
# use and_()
from sqlalchemy import and_
query.filter(and_(User.name == ‘ed’, User.fullname == ‘Ed Jones’))

# or send multiple expressions to .filter()
query.filter(User.name == 'ed', User.fullname == 'Ed Jones')
# or chain multiple filter()/filter_by() calls
query.filter(User.name == 'ed').filter(User.fullname == 'Ed Jones')

Note: Makesureyouuseand_()andnotthePythonandoperator! • OR:

Note: Makesureyouuseor_()andnotthePythonoroperator! • MATCH:

query.filter(User.name.match(‘wendy’))
Note: match() uses a database-specific MATCH or CONTAINS f

原文:http://www.cnblogs.com/alex3714/articles/5978329.html

Python虚拟环境工具Virtualenv的安装与使用

简介

Virtualenv可以为Python提供独立的运行环境,在一定程度上可解决解决依赖、版本以及间接权限等问题。

安装

使用pip命令安装:

$ [sudo] pip install virtualenv  

或使用

$ [sudo] pip install https://github.com/pypa/virtualenv/tarball/master  

安装最新版本。

使用

创建虚拟环境

$ virtualenv venv  

目前版本默认不使用全局Python安装的库,即参数–no-site-packages。如果要继承全局Python的库,则

$ virtualenv --system-site-packages venv  

指定Python的解释器:

$ virtualenv -p /usr/bin/python3.5  venv  

激活虚拟环境

使用前,需要先激活虚拟环境

source venv/bin/activate  

注意此时命令行会多一个(ENV),ENV为虚拟环境名称,接下来所有模块都只会安装到该目录中。

退出虚拟环境

(ENV)$ deactivate  

删除虚拟环境

退出虚拟环境后,在终端输入命令:

(ENV)$ deactivate  
$ rm -r /path/to/ENV  

PS:

Python3.3以上的版本通过venv模块原生支持虚拟环境,可以代替virtualenv。

CentOS 7.4 安装python3及虚拟环境

由于写了个爬虫脚本,需要放到服务器中运行。之前一直在Ubuntu系统中安装多Python环境,而CentOS系统的安装步骤略微有些出入,故详细记录下这几天趟过的坑。

说明

1.本文的系统命令一般会在语句前加上#号,以区分系统命令及其他内容。输入命令时,无需输入#号。

# yum install vim

2.本文系统输出的信息,会在前面加上>>号。

# which python
>> /usr/bin/python    # 系统输出的信息

3.本文的系统命令都是在root账号下执行的,假如非root账号执行,提示没有权限,可在命令前加sudo。

# yum install vim    #root账号下执行命令
# sudo yum install vim    #非root账号下执行管理员权限命令,需在命令前加`sudo`

4.安装环境

系统版本:CentOS 7.4(自带Python2.7)
安装版本:Python3.6
安装插件:virtualenv、virtualenvwrapper

一、安装Python3

由于CentOS7原本就安装了Python2,而且这个Python2不能被删除,因为有很多系统命令,比如yum都要用到。所以我们要额外安装Python3,而且系统一般允许多个版本的python同时存在。

我们先来查看python安装位置,一般是位于/usr/bin/python目录下。

# which python
>> /usr/bin/python

下面介绍安装Python3的方法:

1. 安装依赖包(切记安装)

# yum -y groupinstall "Development tools"
# yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel

2.下载Python3安装包

大家可根据自己需求下载不同版本的Python3,我下载的是Python3.6.2

# wget https://www.python.org/ftp/python/3.6.2/Python-3.6.2.tar.xz

3. 新建python3存放目录

# mkdir /usr/local/python3 

4. 安装Python3

解压压缩包,进入解压目录,指定安装目录,安装Python3。

# tar -xvJf  Python-3.6.2.tar.xz
# cd Python-3.6.2
# ./configure --prefix=/usr/local/python3
# make && make install

安装Python3时,会自动安装pip。假如没有,需要自己手动安装。

# yum -y install python-pip

5. 创建软链接

# ln -s /usr/local/python3/bin/python3 /usr/bin/python3
# ln -s /usr/local/python3/bin/pip3 /usr/bin/pip3

6. 安装完成,输入python3测试

未分类

二、创建虚拟环境

virtualenv是一个可以在同一计算机中隔离多个python版本的工具。有时,两个不同的项目可能需要不同版本的python,如 python2.7 / python3.6 ,但是如果都装到一起,经常会导致问题。virtualenv能够用于创建独立的Python虚拟环境,多个Python相互独立,互不影响。
virtualenvwrapper这个软件包可以让我们管理虚拟环境变得更加简单。不用再跑到某个目录下通过virtualenv来创建虚拟环境,并且激活的时候也要跑到具体的目录下去激活。

下面介绍安装python虚拟环境的方法:

使用pip安装包前,先更新pip。

# pip3 install --upgrade pip

1. 安装virtualenv、virtualenvwrapper

# pip3 install virtualenv
# pip3 install virtualenvwrapper

2. 进入.bashrc文件中,定义virtualenvwrapper路径

使用vim编辑.bashrc文件

# vim ~/.bashrc

在文末填入以下代码并保存

VIRTUALENVWRAPPER_PYTHON=/usr/local/python3/bin/python3    # 指定virtualenvwrapper执行的python版本
export WORKON_HOME=$HOME/.virtualenvs    # 指定虚拟环境存放目录,.virtualenvs目录名可自拟
source /usr/local/bin/virtualenvwrapper.sh    # virtualenvwrapper.sh所在目录

3. 运行.bashrc文件

# source ~/.bashrc

4. 创建虚拟环境

# mkvirtualenv py3-env

也可指定虚拟环境的python版本

# mkvirtualenv --python=/usr/bin/python3 py3-env  

5. 进入虚拟环境中,然后进入到项目所在目录,安装好相应的包(如无需要,可跳过此步)

#  pip install -r requirements.txt

虚拟环境搭建完成!

常见的virtualenvwrapper命令

  • 创建虚拟环境
# mkvirtualenv my_env
  • 切换到某个虚拟环境
# workon my_env
  • 退出当前虚拟环境
# deactivate
  • 删除某个虚拟环境
# rmvirtualenv my_env
  • 列出所有虚拟环境
# lsvirtualenv
  • 进入到虚拟环境所在的目录
# cdvirtualenv

三、异常情况

  • 假如source ~/.bashrc时,提示以下错误
# source ~/.bashrc
>> -bash: /usr/local/bin/virtualenvwrapper.sh: No such file or directory

【原因】
.bashrc文件中的virtualenvwrapper.sh所在目录错误。

【解决方案】
①查找virtualenvwrapper.sh所在目录

# find / -name "virtualenvwrapper.sh"
>> /usr/local/python3/bin/virtualenvwrapper.sh

②把.bashrc文件的virtualenvwrapper.sh目录更改为实际所在目录

source /usr/local/python3/bin/virtualenvwrapper.sh    # virtualenvwrapper.sh实际所在目录
  • 假如创建虚拟环境时,提示以下错误
# mkvirtualenv my_env
>> ERROR: virtualenvwrapper could not find virtualenv in your path

【解决方案】
①查找virtualenv所在目录

# find / -name "virtualenv"
>> /usr/local/python3/bin/virtualenv

②创建软链接

#  ln -s /usr/local/python3/bin/virtualenv /usr/local/bin/virtualenv

使用Docker Compose部署python应用

这篇文章我们通过Docker Compose来运行部署一个简单的Python web应用,我们将使用Flask框架和Redis。

预备的东西

  • 安装好Docker
  • 安装好Docker Compose

定义应用的依赖

1、创建项目目录

mkdir composetest
cd composetest

2、创建应用文件app.py

在项目根目录composetest下创建并打开app.py文件,编写如下代码:

import time

import redis
from flask import Flask


app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)


def get_hit_count():
    retries = 5
    while True:
        try:
            return cache.incr('hits')
        except redis.exceptions.ConnectionError as exc:
            if retries == 0:
                raise exc
            retries -= 1
            time.sleep(0.5)


@app.route('/')
def hello():
    count = get_hit_count()
    return 'Hello World! I have been seen {} times.n'.format(count)

if __name__ == "__main__":
    app.run(host="0.0.0.0", debug=True)

这里,redis是应用网络上edis容器的主机名,我们使用Redis的默认端口:6379。

3、创建应用requirements.txt文件

在项目根目录composetest下创建requirements.txt文件,编辑文件:

flask
redis

创建Dockerfile文件

我们写个Dockerfile文件来构建Docker镜像,该镜像会包含该Python应用的所有依赖,包括Python本身。

在项目根目录composetest下创建Dockerfile文件并编辑文件:

FROM python:3.4-alpine
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
CMD ["python", "app.py"]

该文件告诉Docker完成以下工作:

  • 构建一个以Python 3.4镜像为基础镜像的镜像.
  • 把当前目录 . 复制到镜像的 /code 路径下.
  • 设置工作目录为 /code .
  • 安装Python依赖.
  • 设置容器的默认命令.

在Compose文件定义服务

在项目根目录composetest下创建docker-compose.yml文件并编辑:

version: '3'
services:
  web:
    build: .
    ports:
     - "5000:5000"
  redis:
    image: "redis:alpine"

该Compose文件定义两个服务:web和redis。该web服务将

  • 使用从Dockerfile文件构建的镜像.
  • 暴露容器的5000端口映射到宿主机的5000端口。我们使用Flask的web服务器默认端口 5000.

redis服务使用从Docker Hub registry仓库拉取的公有Redis镜像。

使用Compose构建和运行app

在项目根目录composetest下启动运行应用:

$ docker-compose up
Starting composetest_web_1   ... done
Starting composetest_redis_1 ... done
Attaching to composetest_redis_1, composetest_web_1
redis_1  | 1:C 05 May 02:38:07.354 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1  | 1:C 05 May 02:38:07.354 # Redis version=4.0.9, bits=64, commit=00000000, modified=0, pid=1, just started
redis_1  | 1:C 05 May 02:38:07.354 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis_1  | 1:M 05 May 02:38:07.355 * Running mode=standalone, port=6379.
redis_1  | 1:M 05 May 02:38:07.355 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
redis_1  | 1:M 05 May 02:38:07.355 # Server initialized
redis_1  | 1:M 05 May 02:38:07.355 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
redis_1  | 1:M 05 May 02:38:07.355 * DB loaded from disk: 0.000 seconds
redis_1  | 1:M 05 May 02:38:07.355 * Ready to accept connections
web_1    |  * Serving Flask app "app" (lazy loading)
web_1    |  * Environment: production
web_1    |    WARNING: Do not use the development server in a production environment.
web_1    |    Use a production WSGI server instead.
web_1    |  * Debug mode: on
web_1    |  * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
web_1    |  * Restarting with stat
web_1    |  * Debugger is active!
web_1    |  * Debugger PIN: 320-444-115
web_1    | 172.18.0.1 - - [05/May/2018 02:38:11] "GET / HTTP/1.1" 200 -

Compose拉取Redis镜像,为我们的应用构建一个镜像,并开始我们定义的服务。这种情况,代码在构建时是被静态地复制到镜像里。

打开浏览器,输入http://0.0.0.0:5000/, 会看到页面输出:

Hello World! I have been seen 1 times.

刷新页面,这里的数字会顺序递增

Hello World! I have been seen 2 times.

打开另一个terminal窗口,输入docker image ls可以看到本地的镜像列表,列表中会看到redis和web:

$ docker image ls
REPOSITORY                       TAG                 IMAGE ID            CREATED             SIZE
composetest_web                  latest              88cd35029579        12 hours ago        94.9MB
springio/gs-spring-boot-docker   latest              6c173fe17a59        26 hours ago        118MB
python                           3.4-alpine          42756b6e26a0        2 weeks ago         83.6MB
hello-world                      latest              e38bc07ac18e        3 weeks ago         1.85kB
redis                            alpine              98bd7cfc43b8        5 weeks ago         27.8MB
openjdk                          8-jdk-alpine        224765a6bdbe        3 months ago        102MB

要停止应用,可以输入docker-compose down命令或者按CTRL + C。

修改Compose文件

编辑docker-compose.yml,为web服务添加一个bind mount:

version: '3'
services:
  web:
    build: .
    ports:
     - "5000:5000"
    volumes:
     - .:/code
  redis:
    image: "redis:alpine"

新添加的 volume 键将宿主机的项目目录挂载到容器里的 /code 目录,这样我们可以即时地修改代码,而不用重新构建镜像。

重新构建和运行应用

项目根目录下输入 docker-compose up 重新构建并运行修改Compose文件后的应用

$ docker-compose up
Creating network "composetest_default" with the default driver
Creating composetest_web_1 ...
Creating composetest_redis_1 ...
Creating composetest_web_1
Creating composetest_redis_1 ... done
Attaching to composetest_web_1, composetest_redis_1
web_1    |  * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
...

刷新浏览器,会看到计数依然会递增。

更新应用

现在项目代码已经通过 volume 被挂载到容器,我们可以修改代码并即时看到变化,而不用重新构建镜像。我们编辑修改下 app.py文件,比如将 Hello World! 修改为 Hello from Docker!:

return 'Hello from Docker! I have been seen {} times.n'.format(count)

刷新浏览器,页面会相应地更新

未分类

docke-compose其他命令

在后台运行服务:

$ docker-compose up -d

查看当前运行服务:

$ docker-compose ps

查看web服务在使用的环境变量:

$ docker-compose run web env

停止服务:

$ docker-compose stop

停止并删除容器、网络、镜像和volumes卷

$ docker-compose down --volumes

关于 Python 垃圾回收机制的初步认识

一、前言

  Python 是一门高级语言,使用起来类似于自然语言,开发的时候自然十分方便快捷,原因是Python在背后为我们默默做了很多事情,其中一件就是垃圾回收,来解决内存管理,内存泄漏的问题。

  内存泄漏:当程序不停运行,有一部分对象没有作用,但所占内存没有被释放,服务器内存随时间越来越少,最终导致系统的崩溃,所以内存泄漏是一个需要重点关注的问题。

二、引用计数

Python 标记一个对象是否还有用的方法就是用引用计数,以下情形会为该对象的计数+1:

  1. 创建时

  2. 被引用时

  3. 作为参数传入函数时

相反,以下情形会为该对象的计数-1:

  1. 被del

  2. 被重引用

  3. 函数执行完毕

查看某一元素的计数可以通过 sys.getrefcount(),当引用计数为0 的时候,内存就会被释放。

可以想到和其他垃圾回收相比,Python的机制优点很明显,就是实时性,Python的gc 模块就是开放的接口用以管理。

也可以很容易猜到这样的缺点就是性能相对较低,看过这样的报道,instagram 通过禁用 gc 模块,性能提升10%!

三、 循环引用

有一种特殊情况,当两个或多个变量互相循环引用的时候,按照计数引用的机制就无法处理了

a = []
b = []
a.append(b)
b.append(a)
print(a,b)

a,b 的引用计数均为2,无法回收两者内存

四、解决方案

1、通过 ”标记-清除“ 来解决循环调用问题:

垃圾回收器定时去寻找这类循环调用,并清除

具体是 先从 根对象集合副本中 开始寻找,这些对象计数不为0,没有被清除

然后一个个检测,将其分为可达对象和不可达对象,底层通过链表的数据结构实现,通过操作副本清除标记,来在不影响原数据的情况下,判断是否为循环调用

最后将不可达对象清除,释放内存,效率较低。    

有三种情况会触发垃圾回收:

  1. 调用gc.collect(),
  2. 当gc模块的计数器达到阀值的时候。
  3. 程序退出的时候

2、分代回收,利用 “空间换时间”策略提高效率:

有些内存块生存时间从开始到结束,有些则很短,所以同样对他们进行垃圾回收是很浪费的一件事情,

所有对象开始被划分到零代中,Python 默认 有三代,一个代就是一个链表

年轻代中的对象优先处理,经历垃圾处理次数愈多的,越“老资格” ,就会上升,最终放在第二代中。

备注:

Python的垃圾回收机制是通过检测数量是否到达阈值来决定是否进行。

Python 这方面源码是c写的,暂时看不懂,留待以后搞懂链表结构再来研究,

gc 模块 留待以后研究。

uwsgi的python2+3多版本共存

1、首先,机器需要有python2和python3的可执行环境。

确保pip和pip3命令可用。原理就是在哪个环境下安装uwsgi。uwsgi启动的时候,就用的哪个python版本

未分类

2、安装virtualenv环境管理工具

未分类

3、创建python2和python3的虚拟环境

未分类

4、进入python2虚拟环境

未分类

5、进入python3虚拟环境

未分类

常规发布应用的时候。可以编写shell脚本执行相应的命令启动即可,如下

未分类

python多环境管理工具virtualenv

系统环境

CentOS 7

安装

通过pip直接安装
pip install virtualenv

使用示例

# 在/usr/local/下面创建一个virtualenv目录,作为多环境管理用目录
mkdir /usr/local/virtualenv

# 进入上面创建的目录
cd /usr/local/virtualenv

# 创建一个名为env1的python环境(这里没加参数,该命令其实有很多参数可用)
virtualenv env1

# 执行之后,目录下会创建一个env1目录,如果想切换到env1环境下,则执行一下命令
source env1/bin/activate

使用扩展包

为了更简便的切换和管理virtualenv环境,可以借助virtualenvwrapper扩展包

安装扩展包

pip install virtualenvwrapper

配置环境变量,可在/etc/profile里添加如下指令

# 指定工作空间,可以自己随意创建
WORKON_HOME=/usr/local/virtualenv
# /usr/bin/virtualenvwrapper.sh是安装扩展包后生成的,不同的系统可能生成的文件路径不同
source /usr/bin/virtualenvwrapper.sh

常用命令

# 创建环境
mkvirtualenv [环境名]

# 切换到环境;后面不跟环境名,可以显示出所有环境
workon [环境名]

# 查看已有的环境
lsvirtualenv

# 查看当前环境中已安装的包
lssitepackages

# 退出当前环境
deactivate

Ubuntu下Python设置pip使用国内源站

在用户目录下建立.pip/pip.conf文件

cd ~/ && mkdir .pip
cd .pip && nano pip.conf

写入以下配置并保存即可

[global]
index-url = https://pypi.douban.com/simple/

当然,还可以选择使用清华,阿里等源站

清华:https://pypi.tuna.tsinghua.edu.cn/simple
阿里: https://mirrors.aliyun.com/pypi/simple

未分类

在CentOS上安装Python3的三种方法

未分类

Centos7默认自带了Python2.7版本,但是因为项目需要使用Python3.x你可以按照此文的三个方法进行安装.

注:本文示例安装版本为Python3.5,

一、Python源代码编译安装

安装必要工具 yum-utils ,它的功能是管理repository及扩展包的工具 (主要是针对repository)

$ sudo yum install yum-utils

使用yum-builddep为Python3构建环境,安装缺失的软件依赖,使用下面的命令会自动处理.

$ sudo yum-builddep python

完成后下载Python3的源码包(笔者以Python3.5为例),Python源码包目录: https://www.python.org/ftp/python/ ,截至发博当日Python3的最新版本为 3.7.0

$ curl -O https://www.python.org/ftp/python/3.5.0/Python-3.5.0.tgz

最后一步,编译安装Python3,默认的安装目录是 /usr/local 如果你要改成其他目录可以在编译(make)前使用 configure 命令后面追加参数 “–prefix=/alternative/path” 来完成修改。

$ tar xf Python-3.5.0.tgz
$ cd Python-3.5.0
$ ./configure
$ make
$ sudo make install

至此你已经在你的CentOS系统中成功安装了python3、pip3、setuptools,查看python版本

$ python3 -V

如果你要使用Python3作为python的默认版本,你需要修改一下 bashrc 文件,增加一行alias参数

alias python='/usr/local/bin/python3.5'

由于CentOS 7建议不要动/etc/bashrc文件,而是把用户自定义的配置放入/etc/profile.d/目录中,具体方法为

vi /etc/profile.d/python.sh

输入alias参数 alias python=’/usr/local/bin/python3.5’,保存退出

如果非root用户创建的文件需要注意设置权限

chmod 755 /etc/profile.d/python.sh

重启会话使配置生效

source /etc/profile.d/python.sh

二、从EPEL仓库安装

最新的EPEL 7仓库提供了Python3(python 3.4)的安装源,如果你使用CentOS7或更新的版本的系统你也可以按照下面的步骤很轻松的从EPEL仓库安装。

安装最新版本的EPEL

$ sudo yum install epel-release

用yum安装python 3.4:

$ sudo yum install python34

注意:上面的安装方法并未安装pip和setuptools,如果你要安装这两个库可以使用下面的命令:

$ curl -O https://bootstrap.pypa.io/get-pip.py
$ sudo /usr/bin/python3.4 get-pip.py

三、从SCL(Software Collections)仓库安装

最后一种方法是通过Software Collections (SCL) repository来安装,需要注意的是SCL仓库仅支持CentOS 6.5以上版本,最新版的SCL提供了Python3.3版本,具体安装步骤:

$ sudo yum install python33

从SCL中使用python3,你需要一行命令来启用Python3:

$ scl enable python33 <command>

您还可以使用Python编译器来调用一个bash shell:

$ scl enable python33 bash

总结

笔者建议使用前两种方法,老司机使用方法一编译安装;新手使用方法二yum二进制安装,简单方便。

使用Python和Flask编写Prometheus监控

Installation

pip install flask
pip install prometheus_client

Metrics

Prometheus提供4种类型Metrics:Counter, Gauge, Summary和Histogram

Counter

Counter可以增长,并且在程序重启的时候会被重设为0,常被用于任务个数,总处理时间,错误个数等只增不减的指标。

import prometheus_client
from prometheus_client import Counter
from prometheus_client.core import CollectorRegistry
from flask import Response, Flask
app = Flask(__name__)
requests_total = Counter("request_count", "Total request cout of the host")
@app.route("/metrics")
def requests_count():
    requests_total.inc()
    # requests_total.inc(2)
    return Response(prometheus_client.generate_latest(requests_total),
                    mimetype="text/plain")
@app.route('/')
def index():
    requests_total.inc()
    return "Hello World"
if __name__ == "__main__":
    app.run(host="0.0.0.0")

运行改脚本,访问youhost:5000/metrics

# HELP request_count Total request cout of the host
# TYPE request_count counter
request_count 3.0

Gauge

Gauge与Counter类似,唯一不同的是Gauge数值可以减少,常被用于温度、利用率等指标。

import random
import prometheus_client
from prometheus_client import Gauge
from flask import Response, Flask
app = Flask(__name__)
random_value = Gauge("random_value", "Random value of the request")
@app.route("/metrics")
def r_value():
    random_value.set(random.randint(0, 10))
    return Response(prometheus_client.generate_latest(random_value),
                    mimetype="text/plain")
if __name__ == "__main__":
    app.run(host="0.0.0.0")

运行改脚本,访问youhost:5000/metrics

# HELP random_value Random value of the request
# TYPE random_value gauge
random_value 3.0

Summary/Histogram

Summary/Histogram概念比较复杂,一般exporter很难用到,暂且不说。

PLUS

LABELS

使用labels来区分metric的特征

from prometheus_client import Counter
c = Counter('requests_total', 'HTTP requests total', ['method', 'clientip'])
c.labels('get', '127.0.0.1').inc()
c.labels('post', '192.168.0.1').inc(3)
c.labels(method="get", clientip="192.168.0.1").inc()

REGISTRY

from prometheus_client import Counter, Gauge
from prometheus_client.core import CollectorRegistry
REGISTRY = CollectorRegistry(auto_describe=False)
requests_total = Counter("request_count", "Total request cout of the host", registry=REGISTRY)
random_value = Gauge("random_value", "Random value of the request", registry=REGISTRY)