ImportError: pycurl: libcurl link-time ssl backend (openssl) is different from compile-time ssl backend (none/other)解决

 python  ImportError: pycurl: libcurl link-time ssl backend (openssl) is different from compile-time ssl backend (none/other)解决已关闭评论
10月 082019
 

mac下使用import pycurl,出现: ImportError: pycurl: libcurl link-time ssl backend (openssl) is different from compile-time ssl backend (none/other)

 

使用下面方式解决:

pip uninstall pycurl
pip install --compile --install-option="--with-openssl" pycurl


Python中filter、map、reduce、lambda 介绍

 python  Python中filter、map、reduce、lambda 介绍已关闭评论
9月 242019
 

Python中filter, map, reduce, lambda函数介绍

filter(function, sequence):对sequence中的item依次执行function(item),将执行结果为True的item组成一个List/String/Tuple(取决于sequence的类型)返回:
>>> def f(x): return x % 2 != 0 and x % 3 != 0
>>> filter(f, range(2, 25))
[5, 7, 11, 13, 17, 19, 23]
>>> def f(x): return x != ‘a’
>>> filter(f, “abcdef”)
‘bcdef’

map(function, sequence) :对sequence中的item依次执行function(item),见执行结果组成一个List返回:
>>> def cube(x): return x*x*x
>>> map(cube, range(1, 11))
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]
>>> def cube(x) : return x + x

>>> map(cube , “abcde”)
[‘aa’, ‘bb’, ‘cc’, ‘dd’, ‘ee’]
另外map也支持多个sequence,这就要求function也支持相应数量的参数输入:
>>> def add(x, y): return x+y
>>> map(add, range(8), range(8))
[0, 2, 4, 6, 8, 10, 12, 14]

reduce(function, sequence, starting_value):对sequence中的item顺序迭代调用function,如果有starting_value,还可以作为初始值调用,例如可以用来对List求和:
>>> def add(x,y): return x + y
>>> reduce(add, range(1, 11))
55 (注:1+2+3+4+5+6+7+8+9+10)
>>> reduce(add, range(1, 11), 20)
75 (注:1+2+3+4+5+6+7+8+9+10+20)

lambda:这是Python支持一种有趣的语法,它允许你快速定义单行的最小函数,类似与C语言中的宏,这些叫做lambda的函数,是从LISP借用来的,可以用在任何需要函数的地方:
>>> g = lambda x: x * 2
>>> g(3)
6
>>> (lambda x: x * 2)(3)
6

我们也可以把filter map reduce 和lambda结合起来用,函数就可以简单的写成一行。
例如
kmpathes = filter(lambda kmpath: kmpath,
map(lambda kmpath: string.strip(kmpath),

string.split(l, ‘:’)))
看起来麻烦,其实就像用语言来描述问题一样,非常优雅。
对 l 中的所有元素以’:’做分割,得出一个列表。对这个列表的每一个元素做字符串strip,形成一个列表。对这个列表的每一个元素做直接返回操作(这个地方可以加上过滤条件限制),最终获得一个字符串被’:’分割的列表,列表中的每一个字符串都做了strip,并可以对特殊字符串过滤

 Posted by at 上午8:09

pip/pip3切换到国内安装源

 python  pip/pip3切换到国内安装源已关闭评论
9月 162019
 

pip/pip3默认安装源国内下载速度实在太慢了,经常出现timeout,可以使用下面的方式切换到ali源,速度还是很给力的!

linux/mac下运行命令
vi ~/.pip/pip.conf

windows:
%HOMEPATH%\pip\pip.ini

然后写入如下内容并保存:
[global]
trusted-host = mirrors.aliyun.com
index-url = https://mirrors.aliyun.com/pypi/simple

Python模板-Mako语法介绍

 python  Python模板-Mako语法介绍已关闭评论
9月 052019
 

资源

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

文档 http://docs.makotemplates.org/en/latest/

文档翻译 Mako模板入门 http://help.42qu.com/code/mako.html

安装

pip install mako

HelloWorld

from mako.template import Template

mytemplate = Template("hello world!")
print mytemplate.render()

-------------------------

from mako.template import Template
print Template("hello ${data}!").render(data="world")

语法

输出变量 ${x}

数学计算 ${1+1}
the contents within the ${} tag are evaluated by Python directly, so full expressions are OK

filter
${"test"|u}
${"test"|u,trim}
内置filter列表
    u : URL escaping, provided by urllib.quote_plus(string.encode('utf-8'))
    h : HTML escaping, provided by markupsafe.escape(string)
    x : XML escaping
    trim : whitespace trimming, provided by string.strip()
    entity : produces HTML entity references for applicable strings, derived from htmlentitydefs
    unicode (str on Python 3): produces a Python unicode string (this function is applied by default)
    decode.<some encoding> : decode input into a Python unicode with the specified encoding
    n : disable all default filtering; only filters specified in the local expression tag will be applied.

分支
% if x == 5:
    abcd
% endif

循环
% for a in ['1', '2', '3']:
    % if a == '1':
      abc
    % elif a == '2':
      def
    % else:
      gh
    % endif
$ endfor

Python语法
this is a template
<%
    x = db.get_resource('foo')
    y = [z.element for z in x if x.frobnizzle==5]
%>
% for elem in y:
    element: ${elem}
% endfor

换行

加 / 强制不换行


设置变量
% for item in ('apple', 'banana'):
    <%
        isBanana = False
    %>
    % if item == 'banana':
    <%
        isBanana = True
    %>
    %endif
    % if isBanana:
        <span> Bought a banana</span>
    %endif
%endfor

注释

## 这是一个注释.
...text ...

多行
<%doc>
这里是注释
更多注释
</%doc>

模块级别语句

<% %> 的一个变体是 <%! %>,代表模块级别的代码块。其中的代码会在模板的模块级别执行,而不是在模板的 rendering 函数中。

<%!
import mylib
import re

def filter(text):
    return re.sub(r'^@', '', text)
%>

标签

定义了当前模板的总体特性,包括缓存参数,以及模板被调用时期待的参数列表(非必须)
<%page args="x, y, z='default'"/>
<%page cached="True" cache_type="memory"/>


<%include file="header.html"/>
hello world
<%include file="footer.html"/>

%def 标签用于定义包含一系列内容的一个 Python 函数,此函数在当前模板的其他某个地方被调用到
<%def name="myfunc(x)">
this is myfunc, x is ${x}
</%def>
${myfunc(7)}

<%block filter="h">
some <html> stuff.
</%block>
<%block name="header">
    <h2><%block name="title"/></h2>
</%block>

Mako 中的 %namespace 等价于 Python 里的 import 语句。它允许访问其他模板文件的所有 rendering 函数和元数据
<%namespace file="functions.html" import="*"/>

<%inherit file="base.html"/>

处理多行注释:
<%doc>
    these are comments
    more comments
</%doc>

该标签使得 Mako 的词法器对模板指令的常规解析动作停止,并以纯文本的形式返回其整个内容部分
<%text filter="h">
heres some fake mako ${syntax}
<%def name="x()">${x}</%def>
</%text>

有时你想中途停止执行一个模板或者 <%def> 方法,只返回已经收集到的文本信息,可以通过在 Python 代码块中使用 return 语句来完成

% if not len(records):
    No records found.
    <% return %>
% endif

文件template

为提高性能,从文件中加载的 Template, 可以将它产生的模块的源代码以普通 python 模块文件的形式(.py),

缓存到文件系统中。只要加一个参数 module_directory 即可做到这一点:

from mako.template import Template

mytemplate = Template(filename='/docs/mytmpl.txt', module_directory='/tmp/mako_modules')
print mytemplate.render()

当上述代码被 render 的时候,会创建文件 /tmp/mako_modules/docs/mytmpl.txt.py.

下一次 Template 对象被用同样参数调用的时候,就会直接重用该模块文件。

文件TemplateLookup

#有一个对 header.txt 文件的包含引用。而从何处去查找 header.txt, 则由 TemplateLookup 指明,是 "/docs" 目录
from mako.template import Template
from mako.lookup import TemplateLookup

mylookup = TemplateLookup(directories=['/docs'])
mytemplate = Template("""<%include file="header.txt"/> hello world!""", lookup=mylookup)


--------------

#可以直接通过 TemplateLookup 来获取模板对象,利用 TemplateLookup 的 get_template 方法,
#并传递模板的 URI 作为参数
mylookup = TemplateLookup(directories=['/docs'], output_encoding='utf-8', encoding_errors='replace')
mytemplate = mylookup.get_template("foo.txt")
print mytemplate.render()

-------------
参数
mylookup = TemplateLookup(directories=['/docs'], output_encoding='utf-8', encoding_errors='replace', , collection_size=500)
TemplateLookup 同时也会在内存中缓存一组模板,所以并不是每一次请求都会导致模板的重新编译和模块重新加载。默认 TemplateLookup 的大小没有限制,但你可以通过 collection_size 参数来限制它
以上的 lookup 会持续加载模板到内存中,直到达到 500 的时候,它就会清除掉一定比例的模板缓存项,根据“最近最少访问”原则

另一个 TemplateLookup 相关的标志是  filesystem_checks. 默认为 True,
每一次 get_template() 方法返回模板后,原始的模板文件的 revision time 会和上次加载模板的时间做对比,
如果文件更新,则会加载其内容,并重新编译该模板。
在生产环境下,设置 filesystem_checks 为 False 可以带来一定的性能提升(和具体的文件系统有关)

自己创建context

from mako.template import Template
from mako.runtime import Context
from StringIO import StringIO

mytemplate = Template("hello, ${name}!")
buf = StringIO()
ctx = Context(buf, name="jack")
mytemplate.render_context(ctx)
print buf.getvalue()

其他

1.解决mako中文乱码问题

TemplateLookup(... , output_encoding='utf-8', ...)
Template(..., input_encoding='utf-8')
又在mako的模板文件的首行添加
## -*- encoding:utf8 -*-

单星号与双星号(*和**)在python函数中的应用

 python  单星号与双星号(*和**)在python函数中的应用已关闭评论
9月 042019
 

想不到单星号还能用于解压参数列表!!

在python的函数中经常能看到输入的参数前面有一个或者两个星号:例如

这两种用法其实都是用来将任意个数的参数导入到python函数中。

单星号(*):*args
将所以参数以元组(tuple)的形式导入:
例如:

双星号(**):**kwargs
将参数以字典的形式导入

此外,单星号的另一个用法是解压参数列表:(这种用法让人惊艳!)

当然这两个用法可以同时出现在一个函数中:例如

centos 7.6 下python2.7 安装 MySQL-python问题解决

 python  centos 7.6 下python2.7 安装 MySQL-python问题解决已关闭评论
5月 162019
 

centos7.6 下python2.7版本使用pip install MySQL-python可能出现下面错误:

可能问题一:  ERROR: Complete output from command python setup.py egg_info:
ERROR: sh: mysql_config: 未找到命令

解决办法: yum install mysql-devel

 

再次安装,没问题最好, 如果出现下面问题:

 可能问题二:_mysql.c:29:20: 致命错误:Python.h:没有那个文件或目录
#include “Python.h”

解决办法: yum install python-devel

 

再次安装 : pip install MySQL-python

问题解决!

 

mac下安装MySQL_python时出现_mysql.c:44:10: fatal error: ‘my_config.h’ file not found

 python  mac下安装MySQL_python时出现_mysql.c:44:10: fatal error: ‘my_config.h’ file not found已关闭评论
12月 242018
 

mac下使用brew install mysql,安装pip install MySQL-python出现下面错误提示: 

    _mysql.c:44:10: fatal error: ‘my_config.h’ file not found
    #include “my_config.h”
             ^~~~~~~~~~~~~
    1 error generated.
    error: command ‘cc’ failed with exit status 1

网上很多方法都无效,使用下面都步骤可解决

brew remove mysql
brew install mysql@5.7
brew link --force mysql@5.7
pip install msyql-python (如权限不足,请使用sudo)

python3安装turtle提示错误:Command “python setup.py egg_info” failed with error code 1 错误解决

 python  python3安装turtle提示错误:Command “python setup.py egg_info” failed with error code 1 错误解决已关闭评论
12月 022018
 

 使用pip在python3.6.4安装turtle时出现下面错误:

Collecting turtle

  Using cached https://files.pythonhosted.org/packages/ff/f0/21a42e9e424d24bdd0e509d5ed3c7dfb8f47d962d9c044dba903b0b4a26f/turtle-0.0.2.tar.gz

    Complete output from command python setup.py egg_info:

    Traceback (most recent call last):

      File “<string>”, line 1, in <module>

      File “/tmp/pip-install-hpqxw6_s/turtle/setup.py”, line 40

        except ValueError, ve:

                         ^

    SyntaxError: invalid syntax

    —————————————-

Command “python setup.py egg_info” failed with error code 1 in /xxx/turtle/

其实仔细看是一个语法错误,可以根据上面的url(https://files.pythonhosted.org/packages/ff/f0/21a42e9e424d24bdd0e509d5ed3c7dfb8f47d962d9c044dba903b0b4a26f/turtle-0.0.2.tar.gz)自己先把包下载到本地,然后解压到本地再安装,提示的错误在解压的setup.py文件里面,

  1. 打开setup.py文件,第40行修改为 except (ValueError, ve):
    原来的是Python2的写法,没有括号,加了括号之后Python3就能用了。
  2. 用pip3安装: pip install -e turtle-0.0.2
    -e后面接上我们修改过setup.py文件的目录。
  3. 这样就搞定了。

真正实现tornado异步非阻塞(gen.coroutine,ThreadPoolExecutor,Celery)

 python, tornado  真正实现tornado异步非阻塞(gen.coroutine,ThreadPoolExecutor,Celery)已关闭评论
11月 292018
 

真正实现tornado异步非阻塞,来自:https://blog.csdn.net/u013038616/article/details/72821600

其中 Tornado 的定义是 Web 框架和异步网络库,其中他具备有异步非阻塞能力,能解决他两个框架请求阻塞的问题,在需要并发能力时候就应该使用 Tornado

但是在实际使用过程中很容易把 Tornado 使用成异步阻塞框架,这样对比其他两大框架没有任何优势而言,本文就如何实现真正的异步非阻塞记录。

以下使用的 Python 版本为 2.7.13 
平台为 Macbook
Pro 2016

使用 gen.coroutine 异步编程


Tornado 中两个装饰器:

  • tornado.web.asynchronous

  • tornado.gen.coroutine

asynchronous 装饰器是让请求变成长连接的方式,必须手动调用 self.finish() 才会响应

class MainHandler(tornado.web.RequestHandler):
    @tornado.web.asynchronous
    def get(self):
        # bad 
        self.write("Hello, world")

asynchronous 装饰器不会自动调用self.finish() ,如果没有没有指定结束,该长连接会一直保持直到 pending 状态。 

没有调用self.finish()
所以正确是使用方式是使用了 asynchronous 需要手动 finish

class MainHandler(tornado.web.RequestHandler):
    @tornado.web.asynchronous
    def get(self):
        self.write("Hello, world")
        self.finish()
coroutine 装饰器是指定改请求为协程模式,说明白点就是能使用 yield 配合 Tornado 编写异步程序。

Tronado 为协程实现了一套自己的协议,不能使用 Python 普通的生成器。

在使用协程模式编程之前要知道如何编写 Tornado 中的异步函数,Tornado 提供了多种的异步编写形式:回调、Future、协程等,其中以协程模式最是简单和用的最多。

编写一个基于协程的异步函数同样需要 coroutine 装饰器

@gen.coroutine
def sleep(self):
    yield gen.sleep(10)
    raise gen.Return([1, 2, 3, 4, 5])

这就是一个异步函数,Tornado 的协程异步函数有两个特点:
  • 需要使用 coroutine 装饰器

  • 返回值需要使用 raise
    gen.Return()
     
    当做异常抛出

返回值作为异常抛出是因为在 Python
3.2
之前生成器是不允许有返回值的。

使用过 Python 生成器应该知道,想要启动生成器的话必须手动执行 next() 方法才行,所以这里的 coroutine 装饰器的其中一个作用就是在调用这个异步函数时候自动执行生成器。

使用 coroutine 方式有个很明显是缺点就是严重依赖第三方库的实现,如果库本身不支持 Tornado 的异步操作再怎么使用协程也是白搭依然会是阻塞的,放个例子感受一下。

import time
import logging
import tornado.ioloop
import tornado.web
import tornado.options
from tornado import gen

tornado.options.parse_command_line()

class MainHandler(tornado.web.RequestHandler):
    @tornado.web.asynchronous
    def get(self):
        self.write(“Hello, world”)
        self.finish()

class NoBlockingHnadler(tornado.web.RequestHandler):
    @gen.coroutine
    def get(self):
        yield gen.sleep(10)
        self.write(‘Blocking Request’)

class BlockingHnadler(tornado.web.RequestHandler):
    def get(self):
        time.sleep(10)
        self.write(‘Blocking Request’)

def make_app():
    return tornado.web.Application([
        (r”/”, MainHandler),
        (r”/block”, BlockingHnadler),
        (r”/noblock”, NoBlockingHnadler),
    ], autoreload=True)

if __name__ == “__main__”:
    app = make_app()
    app.listen(8000)
    tornado.ioloop.IOLoop.current().start()


为了显示更明显设置了 10

当我们使用 yield
gen.sleep(10)
 
这个异步的 sleep 时候其他请求是不阻塞的。 
非阻塞效果图
当使用 time.sleep(10) 时候会阻塞其他的请求。 
阻塞效果图
这里的异步非阻塞是针对另一请求来说的,本次的请求该是阻塞的仍然是阻塞的。

gen.coroutine Tornado
3.1
后会自动调用 self.finish() 结束请求,可以不使用 asynchronous 装饰器。

所以这种实现异步非阻塞的方式需要依赖大量的基于 Tornado 协议的异步库,使用上比较局限,好在还是有一些可以用的异步库

基于线程的异步编程


使用 gen.coroutine 装饰器编写异步函数,如果库本身不支持异步,那么响应任然是阻塞的。

Tornado 中有个装饰器能使用 ThreadPoolExecutor 来让阻塞过程编程非阻塞,其原理是在 Tornado 本身这个线程之外另外启动一个线程来执行阻塞的程序,从而让 Tornado 变得阻塞。

futures Python3 是标准库,但是在 Python2 中需要手动安装 
pip
install futures

测试代码

import logging
import tornado.ioloop
import tornado.web
import tornado.options
from tornado import gen
from tornado.concurrent import run_on_executor
from concurrent.futures import ThreadPoolExecutor

tornado.options.parse_command_line()

class MainHandler(tornado.web.RequestHandler):
    @tornado.web.asynchronous
    def get(self):
        self.write(“Hello, world”)
        self.finish()

class NoBlockingHnadler(tornado.web.RequestHandler):
    executor = ThreadPoolExecutor(4)

    @run_on_executor
    def sleep(self, second):
        time.sleep(second)
        return second

    @gen.coroutine
    def get(self):
        second = yield self.sleep(5)
        self.write(‘noBlocking Request: {}’.format(second))

def make_app():
    return tornado.web.Application([
        (r”/”, MainHandler),
        (r”/noblock”, NoBlockingHnadler),
    ], autoreload=True)

if __name__ == “__main__”:
    app = make_app()
    app.listen(8000)
    tornado.ioloop.IOLoop.current().start()

ThreadPoolExecutor 是对标准库中的 threading 的高度封装,利用线程的方式让阻塞函数异步化,解决了很多库是不支持异步的问题。 

这里写图片描述
但是与之而来的问题是,如果大量使用线程化的异步函数做一些高负载的活动,会导致该 Tornado 进程性能低下响应缓慢,这只是从一个问题到了另一个问题而已。

所以在处理一些小负载的工作,是能起到很好的效果,让 Tornado 异步非阻塞的跑起来。

但是明明知道这个函数中做的是高负载的工作,那么你应该采用另一种方式,使用 Tornado 结合 Celery 来实现异步非阻塞。

基于 Celery 的异步编程

Celery 是一个简单、灵活且可靠的,处理大量消息的分布式系统,专注于实时处理的任务队列,同时也支持任务调度。 
Celery
并不是唯一选择,你可选择其他的任务队列来实现,但是 Celery Python 所编写,能很快的上手,同时 Celery 提供了优雅的接口,易于与 Python
Web
框架集成等特点。

Tornado 的配合可以使用 tornado-celery ,该包已经把 Celery 封装到 Tornado 中,可以直接使用。

实际测试中,由于 tornado-celery 很久没有更新,导致请求会一直阻塞,不会返回

解决办法是:

celery 降级到 3.1
pip install celery==3.1 
pika 降级到 0.9.14
pip install pika==0.9.14

import time
import logging
import tornado.ioloop
import tornado.web
import tornado.options
from tornado import gen

import tcelery, tasks

tornado.options.parse_command_line()
tcelery.setup_nonblocking_producer()


class MainHandler(tornado.web.RequestHandler):
    @tornado.web.asynchronous
    def get(self):
        self.write("Hello, world")
        self.finish()


class CeleryHandler(tornado.web.RequestHandler):
    @gen.coroutine
    def get(self):
        response = yield gen.Task(tasks.sleep.apply_async, args=[5])
        self.write('CeleryBlocking Request: {}'.format(response.result))


def make_app(): 
    return tornado.web.Application([
        (r"/", MainHandler),
        (r"/celery-block", CeleryHandler),
    ], autoreload=True)

if __name__ == "__main__":
    app = make_app()
    app.listen(8000)
    tornado.ioloop.IOLoop.current().start()
import os
import time
from celery import Celery
from tornado import gen

celery = Celery("tasks", broker="amqp://")
celery.conf.CELERY_RESULT_BACKEND = os.environ.get('CELERY_RESULT_BACKEND', 'amqp')

@celery.task
def sleep(seconds):
    time.sleep(float(seconds))
    return seconds

if __name__ == "__main__":
    celery.start()

这里写图片描述

Celery Worker 运行在另一个进程中,独立于 Tornado 进程,不会影响 Tornado 运行效率,在处理复杂任务时候比进程模式更有效率。

总结


方法

优点

缺点

可用性

gen.coroutine

简单、优雅

需要异步库支持

★★☆☆☆

线程

简单

可能会影响性能

★★★☆☆

Celery

性能好

操作复杂、版本低

★★★☆☆

目前没有找到最佳的异步非阻塞的编程模式,可用的异步库比较局限,只有经常用的,个人编写异步库比较困难。

推荐使用线程和 Celery 的模式进行异步编程,轻量级的放在线程中执行,复杂的放在 Celery 中执行。当然如果有异步库使用那最好不过了。

Python
3
中可以把 Tornado 设置为 asyncio 的模式,这样就使用
兼容
asyncio 模式的库,这应该是日后的方向。

Reference


celery  [‘selərɪ]  详细X

基本翻译
n. [园艺] 芹菜

网络释义
Celery: 芹菜
celery salt: 香芹盐
celery sticks: 芹菜杆

使用Matplotlib一步步绘制函数图像

 Matplotlib, python  使用Matplotlib一步步绘制函数图像已关闭评论
11月 232018
 

文章循序渐进、清晰明了的介绍了使用matplotlib画一个函数的过程,分享下:https://www.jianshu.com/p/b1dee69767d3

matplotlib 是 python 最著名的绘图库,它提供了一整套和 matlab 相似的命令 API,十分适合交互式进行绘图。

它的文档相当完备,并且 Gallery 页面 中有上百幅缩略图,打开之后都有源程序。因此如果你需要绘制某种类型的图,只需要在这个页面中浏览/复制/粘贴一下,基本上都能搞定。

这是要实现的效果图,利用 Matplotlib 绘制函数 y = x2 的图像。

image

代码实现

import matplotlib.pyplot as plt import numpy as np # 定义 x 变量的范围 (-3,3) 数量 50  x=np.linspace(-3,3,50)
y=x**2 # Figure 并指定大小 plt.figure(num=3,figsize=(8,5)) # 绘制 y=x^2 的图像,设置 color 为 red,线宽度是 1,线的样式是 -- plt.plot(x,y,color='red',linewidth=1.0,linestyle='--') # 设置 x,y 轴的范围以及 label 标注 plt.xlim(-1,2)
plt.ylim(-2,3)
plt.xlabel('x')
plt.ylabel('y') # 设置坐标轴刻度线  # Tick X 范围 (-1,2) Tick Label(-1,-0.25,0.5,1.25,2) 刻度数量 5 个 new_ticks=np.linspace(-1,2,5)
plt.xticks(new_ticks) # Tick Y 范围(-2.2,-1,1,1.5,2.4) ,Tick Label (-2.2, -1, 1, 1.5, 2.4) 别名(下面的英文) plt.yticks([-2.2,-1,1,1.5,2.4],
          [r'$really\ bad$',r'$bad$',r'$normal$',r'$good$',r'$really\ good$']) # 设置坐标轴 gca() 获取坐标轴信息 ax=plt.gca() # 使用.spines设置边框:x轴;将右边颜色设置为 none。 # 使用.set_position设置边框位置:y=0的位置;(位置所有属性:outward,axes,data) ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none') # 移动坐标轴 # 将 bottom 即是 x 坐标轴设置到 y=0 的位置。 ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data',0)) # 将 left 即是 y 坐标轴设置到 x=0 的位置。 ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data',0)) # 设置标签 ax.set_title('y = x^2',fontsize=14,color='r') # 显示图像 plt.show()

首先一幅 Matplotlib 的图像组成部分介绍。

image

基本构成

在 matplotlib 中,整个图像为一个 Figure 对象。在 Figure 对象中可以包含一个或者多个 Axes 对象。每个 Axes(ax) 对象都是一个拥有自己坐标系统的绘图区域。

所属关系如下(图片来自网络):

image

图上:Title 为图像标题,Axis 为坐标轴, Label 为坐标轴标注,Tick 为刻度线,Tick Label 为刻度注释。

各个对象关系可以梳理成以下内容(图片来自网络):

image

Matplotlib 绘图步骤分析

image

注意

这里不讲解 matplotlib 的安装,我使用的是 Anaconda 的 notebook,因此,可以直接导入 matplotlib 的module,想要安装 Anaconda 的请查看的写的另一篇文章。墙裂推荐 Anaconda | 安利 Python IDE

如果说不想使用 Anaconda,可以看看这篇推荐文章,教你如何安装 matplotlib(视频和文章教程)— 莫烦 Python — Matplotlib

上面虽然贴了全部的代码,有 matplotlib 基础的人一看便懂,但是对于初学者来说,就比较抓脑了。

一、matplotlib 实现简单图像

image

使用import导入模块matplotlib.pyplot,并简写成plt使用import导入模块numpy,并简写成np。

#导入 module import matplotlib.pyplot as plt import numpy as np

使用np.linspace定义 x:范围是 (-3,3),个数是50,仿真一维数据组 (x,y) 表示曲线。

# 定义 x 变量的范围 (-3,3) 数量 50  x=np.linspace(-3,3,50)
y=x**2 

使用plt.figure定义一个图像窗口,使用plt.plot画 (x,y) 曲线,使用plt.show显示图像。

#绘制及显示 plt.figure()
plt.plot(x, y)
plt.show()

最终代码

import matplotlib.pyplot as plt import numpy as np # 定义 x 变量的范围 (-3,3) 数量 50  x=np.linspace(-3,3,50)
y=x**2 plt.figure()
plt.plot(x, y)
plt.show()

运行结果

image

看到这个,是不是和最终效果图差距很大,没关系,我们接着往下看。

二、设置 Figure 图像

使用plt.figure定义一个图像窗口:编号为 3,大小为 (8, 5)。使用plt.plot画(x,y)曲线,曲线的颜色属性(color)为红色。曲线的宽度(linewidth)为1.0。曲线的类型(linestyle)为虚线, 使用plt.show显示图像。

plt.figure(num=3,figsize=(8,5))
plt.plot(x,y,color='red',linewidth=1.0,linestyle='--')

最终代码

import matplotlib.pyplot as plt import numpy as np # 定义 x 变量的范围 (-3,3) 数量 50  x=np.linspace(-3,3,50)
y=x**2 # Figure 并指定大小 plt.figure(num=3,figsize=(8,5)) # 绘制 y=x^2 的图像,设置 color 为 red,线宽度是 1,线的样式是 -- plt.plot(x,y,color='red',linewidth=1.0,linestyle='--')

plt.show()

运行效果

image

三、设置坐标轴

设置 x,y 轴坐标范围及标注 label

使用plt.xlim设置x坐标轴范围:(-1, 2); 使用plt.ylim设置 y 坐标轴范围:(-2, 3);

使用plt.xlabel设置 x 坐标轴名称:’x’; 使用plt.ylabel设置 y 坐标轴名称:’I am y’;

代码实现

import matplotlib.pyplot as plt import numpy as np # 定义 x 变量的范围 (-3,3) 数量 50  x=np.linspace(-3,3,50)
y=x**2 # Figure 并指定大小 plt.figure(num=3,figsize=(8,5)) # 绘制 y=x^2 的图像,设置 color 为 red,线宽度是 1,线的样式是 -- plt.plot(x,y,color='red',linewidth=1.0,linestyle='--') # 设置 x,y 轴的范围以及 label 标注 plt.xlim(-1,2)
plt.ylim(-2,3)
plt.xlabel('x')
plt.ylabel('y')

plt.show()

运行结果

image

设置 x, y 刻度范围及刻度标注

设置 x 轴:使用np.linspace定义范围以及个数:范围是(-1,2); 个数是 5。

使用plt.xticks设置 x 轴刻度:范围是(-1,2); 个数是5。

设置 y 轴:使用plt.yticks设置 y 轴刻度以及名称:刻度为 [-2, -1.8, -1, 1.22, 3];对应刻度的名称为 [‘really bad’,’bad’,’normal’,’good’, ‘really good’]。

# 设置坐标轴刻度线  # Tick X 范围 (-1,2) Tick Label(-1,-0.25,0.5,1.25,2) 刻度数量 5 个 new_ticks=np.linspace(-1,2,5)
plt.xticks(new_ticks) # Tick Y 范围(-2.2,-1,1,1.5,2.4) ,Tick Label (-2.2, -1, 1, 1.5, 2.4) 别名(下面的英文) plt.yticks([-2.2,-1,1,1.5,2.4],
          [r'$really\ bad$',r'$bad$',r'$normal$',r'$good$',r'$really\ good$'])

最终代码

import matplotlib.pyplot as plt import numpy as np # 定义 x 变量的范围 (-3,3) 数量 50  x=np.linspace(-3,3,50)
y=x**2 # Figure 并指定大小 plt.figure(num=3,figsize=(8,5)) # 绘制 y=x^2 的图像,设置 color 为 red,线宽度是 1,线的样式是 -- plt.plot(x,y,color='red',linewidth=1.0,linestyle='--') # 设置 x,y 轴的范围以及 label 标注 plt.xlim(-1,2)
plt.ylim(-2,3)
plt.xlabel('x')
plt.ylabel('y') # 设置坐标轴刻度线  # Tick X 范围 (-1,2) Tick Label(-1,-0.25,0.5,1.25,2) 刻度数量 5 个 new_ticks=np.linspace(-1,2,5)
plt.xticks(new_ticks) # Tick Y 范围(-2.2,-1,1,1.5,2.4) ,Tick Label (-2.2, -1, 1, 1.5, 2.4) 别名(下面的英文) plt.yticks([-2.2,-1,1,1.5,2.4],
          [r'$really\ bad$',r'$bad$',r'$normal$',r'$good$',r'$really\ good$']) # 显示图像 plt.show()

运行效果,注意看 x, y 轴刻度以及标注变化

image

四、移动坐标轴

隐藏右边框和上边框:

  1. 使用plt.gca获取当前坐标轴信息。

  2. 使用.spines设置边框:右侧边框;使用.set_color设置边框颜色:默认白色;

    使用.spines设置边框:上边框;使用.set_color设置边框颜色:默认白色;

调整坐标轴至中心(将 left 边框调整到 x=0 处,将 bottom 边框调整到 y=0 处):

  1. 使用.xaxis.set_ticks_position设置 x 坐标刻度数字或名称的位置:bottom。(所有位置:top,bottom,both,default,none)。
  2. 使用.spines设置边框:x 轴;使用.set_position设置边框位置:y=0 的位置;(位置所有属性:outward,axes,data)
# 设置坐标轴 gca() 获取坐标轴信息 ax=plt.gca() # 使用.spines设置边框:x轴;将右边颜色设置为 none。 # 使用.set_position设置边框位置:y=0的位置;(位置所有属性:outward,axes,data) ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none') # 移动坐标轴 # 将 bottom 即是 x 坐标轴设置到 y=0 的位置。 ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data',0)) # 将 left 即是 y 坐标轴设置到 x=0 的位置。 ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data',0))

最终代码

import matplotlib.pyplot as plt import numpy as np # 定义 x 变量的范围 (-3,3) 数量 50  x=np.linspace(-3,3,50)
y=x**2 # Figure 并指定大小 plt.figure(num=3,figsize=(8,5)) # 绘制 y=x^2 的图像,设置 color 为 red,线宽度是 1,线的样式是 -- plt.plot(x,y,color='red',linewidth=1.0,linestyle='--') # 设置 x,y 轴的范围以及 label 标注 plt.xlim(-1,2)
plt.ylim(-2,3)
plt.xlabel('x')
plt.ylabel('y') # 设置坐标轴刻度线  # Tick X 范围 (-1,2) Tick Label(-1,-0.25,0.5,1.25,2) 刻度数量 5 个 new_ticks=np.linspace(-1,2,5)
plt.xticks(new_ticks) # Tick Y 范围(-2.2,-1,1,1.5,2.4) ,Tick Label (-2.2, -1, 1, 1.5, 2.4) 别名(下面的英文) plt.yticks([-2.2,-1,1,1.5,2.4],
          [r'$really\ bad$',r'$bad$',r'$normal$',r'$good$',r'$really\ good$']) # 设置坐标轴 gca() 获取坐标轴信息 ax=plt.gca() # 使用.spines设置边框:x轴;将右边颜色设置为 none。 # 使用.set_position设置边框位置:y=0的位置;(位置所有属性:outward,axes,data) ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none') # 移动坐标轴 # 将 bottom 即是 x 坐标轴设置到 y=0 的位置。 ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data',0)) # 将 left 即是 y 坐标轴设置到 x=0 的位置。 ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data',0)) # 显示图像 plt.show()

运行结果

image

五、设置标题

使用 .set_title 设置标题,声明标题为 y = x2,字体大小 14,颜色为 red。

# 设置标签 ax.set_title('y = x^2',fontsize=14,color='r')

最终代码

import matplotlib.pyplot as plt import numpy as np # 定义 x 变量的范围 (-3,3) 数量 50  x=np.linspace(-3,3,50)
y=x**2 # Figure 并指定大小 plt.figure(num=3,figsize=(8,5)) # 绘制 y=x^2 的图像,设置 color 为 red,线宽度是 1,线的样式是 -- plt.plot(x,y,color='red',linewidth=1.0,linestyle='--') # 设置 x,y 轴的范围以及 label 标注 plt.xlim(-1,2)
plt.ylim(-2,3)
plt.xlabel('x')
plt.ylabel('y') # 设置坐标轴刻度线  # Tick X 范围 (-1,2) Tick Label(-1,-0.25,0.5,1.25,2) 刻度数量 5 个 new_ticks=np.linspace(-1,2,5)
plt.xticks(new_ticks) # Tick Y 范围(-2.2,-1,1,1.5,2.4) ,Tick Label (-2.2, -1, 1, 1.5, 2.4) 别名(下面的英文) plt.yticks([-2.2,-1,1,1.5,2.4],
          [r'$really\ bad$',r'$bad$',r'$normal$',r'$good$',r'$really\ good$']) # 设置坐标轴 gca() 获取坐标轴信息 ax=plt.gca() # 使用.spines设置边框:x轴;将右边颜色设置为 none。 # 使用.set_position设置边框位置:y=0的位置;(位置所有属性:outward,axes,data) ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none') # 移动坐标轴 # 将 bottom 即是 x 坐标轴设置到 y=0 的位置。 ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data',0)) # 将 left 即是 y 坐标轴设置到 x=0 的位置。 ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data',0)) # 设置标签 ax.set_title('y = x^2',fontsize=14,color='r') # 显示图像 plt.show()

运行结果

image

最后,附上 matplotlib 整体结构图(图片来自网络):