标签归档:Python

10行代码绘制漂亮金融K线图,Mplfinance 这个神器你不可错过

近期发现许多小伙伴有绘制K线图的需求,甚至有些同学没有用第三方模块自己写代码绘制图表,其实这完全是重复性工作,网上有许多已经成熟的K线图绘制方案,比如我们今天要讲的 Mplfinance.

Mplfinance 其实是 Matplotlib 组织开源项目的一部分。相对于Matplotlib,Mplfinance这个处于金融行业的垂直领域的模块的关注度确实是少了一些,以至于很多朋友都不知道它的存在,实际上它非常实用且好用。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install --upgrade mplfinance

2.Mplfinance 基本使用

我们以沪深300分钟线为例,使用mplfinance绘制各类金融图形。

首先看看数据结构:

import pandas as pd
mins = pd.read_csv('sh300_1min.csv',index_col=0,parse_dates=True)
print(mins)

结构如下:

                       day      open      high       low     close     volume
0      2022-03-07 10:47:00  4406.223  4406.352  4405.662  4405.922   54345400
1      2022-03-07 10:48:00  4406.172  4406.175  4403.834  4403.918   70803100
2      2022-03-07 10:49:00  4403.333  4403.333  4402.235  4402.340   49632500
3      2022-03-07 10:50:00  4402.330  4402.519  4401.838  4402.519   48159200

我们用于mplfinance的数据必须是 Pandas DataFrame. 字段则按需提供,至少要有时间字段和一列数据。另外原始数据如果是其他的数据类型,你必须得先转成DataFrame格式。

此外,时间字段必须转为DatetimeIndex:

# 公众号:二七阿尔量化
import pandas as pd
import mplfinance as mpf
mins = pd.read_csv('sh300_1min.csv',index_col=0,parse_dates=True)
mins["day"] = pd.to_datetime(mins["day"])
mins = mins.set_index("day")
mins.index.name = 'Time'
print(mins)

效果如下:

                         open      high       low     close     volume
Time
2022-03-07 10:47:00  4406.223  4406.352  4405.662  4405.922   54345400
2022-03-07 10:48:00  4406.172  4406.175  4403.834  4403.918   70803100
2022-03-07 10:49:00  4403.333  4403.333  4402.235  4402.340   49632500
2022-03-07 10:50:00  4402.330  4402.519  4401.838  4402.519   48159200

准备完成后就可以绘制图表了:

# 公众号:二七阿尔量化
import pandas as pd
import mplfinance as mpf
mins = pd.read_csv('sh300_1min.csv',index_col=0,parse_dates=True)
mins["day"] = pd.to_datetime(mins["day"])
mins = mins.set_index("day")
mins.index.name = 'Time'

# 绘制默认图像(美国线)
mpf.plot(mins)

绘制蜡烛图(K线图),为了避免图表过大,我这里只取了240条K线:

# 公众号:二七阿尔量化
import pandas as pd
import mplfinance as mpf
mins = pd.read_csv('sh300_1min.csv',index_col=0,parse_dates=True)
mins["day"] = pd.to_datetime(mins["day"])
mins = mins.set_index("day")
mins.index.name = 'Time'

candle_chart = mins.tail(240)
mpf.plot(candle_chart, type='candle')

黑白颜色太单调了,我们可以换成“雅虎”配色:

mpf.plot(candle_chart, type='candle', style='yahoo')

绘制线型图:

# 公众号:二七阿尔量化
import pandas as pd
import mplfinance as mpf
mins = pd.read_csv('sh300_1min.csv',index_col=0,parse_dates=True)
mins["day"] = pd.to_datetime(mins["day"])
mins = mins.set_index("day")
mins.index.name = 'Time'
mpf.plot(mins, type='line')

除了美国线、蜡烛图(K线)、线型图外,mplfinance还支持 renko、pnf 等图形。有兴趣的同学可以改个type看看效果:

3.添加技术指标

绘制简单移动平均线MA5,我们只需要多加一个参数:

# 公众号:二七阿尔量化
import pandas as pd
import mplfinance as mpf
mins = pd.read_csv('sh300_1min.csv',index_col=0,parse_dates=True)
mins["day"] = pd.to_datetime(mins["day"])
mins = mins.set_index("day")
mins.index.name = 'Time'
candle_chart = mins.tail(240)
mpf.plot(candle_chart, type='candle', mav=5)

如果你需要多条移动平均线,只需要将mav改为元组参数,传入你需要的周期参数:

如果你还需要显示成交量(volume), mplfinance 也能实现:

# 公众号:二七阿尔量化
import pandas as pd
import mplfinance as mpf
mins = pd.read_csv('sh300_1min.csv',index_col=0,parse_dates=True)
mins["day"] = pd.to_datetime(mins["day"])
mins = mins.set_index("day")
mins.index.name = 'Time'
candle_chart = mins.tail(240)
mpf.plot(candle_chart, type='candle', mav=(5, 10, 20), volume=True)

如果你还想给蜡烛上色、想更改线条颜色、想增加其他指标,请看第三部分高级使用。

3.高级使用

上色是非常简单的,正如我们之前换成雅虎配色一样,你只需要添加style参数即可换成我们传统的技术指标颜色。但如果你想自定义颜色也是可以做到的,这里我将前120根柱子设置为蓝黄相间,后120根柱子保留原形:

# 公众号:二七阿尔量化
import pandas as pd
import mplfinance as mpf
mins = pd.read_csv('sh300_1min.csv',index_col=0,parse_dates=True)
mins["day"] = pd.to_datetime(mins["day"])
mins = mins.set_index("day")
mins.index.name = 'Time'
candle_chart = mins.tail(240)
mco = ['yellow','blue'] * 60 + [None] * 120
mpf.plot(candle_chart, volume=True, style='yahoo', type='candle', marketcolor_overrides=mco)

效果如下:

有些同学还希望能够绘制自己的技术指标,mplfinance也可以做到:

# 公众号:二七阿尔量化
# https://github.com/matplotlib/mplfinance/blob/master/examples/mpf_animation_macd.py#L28

import pandas as pd
import mplfinance as mpf
import matplotlib.animation as animation

mins = pd.read_csv('sh300_1min.csv',index_col=0,parse_dates=True)
mins["day"] = pd.to_datetime(mins["day"])
mins = mins.set_index("day")
mins.index.name = 'Time'
candle_chart = mins.tail(240)

df = candle_chart

exp12     = df['close'].ewm(span=12, adjust=False).mean()
exp26     = df['close'].ewm(span=26, adjust=False).mean()
macd      = exp12 - exp26
signal    = macd.ewm(span=9, adjust=False).mean()
histogram = macd - signal

apds = [mpf.make_addplot(exp12,color='lime'),
        mpf.make_addplot(exp26,color='c'),
        mpf.make_addplot(histogram,type='bar',width=0.7,panel=1,
                         color='dimgray',alpha=1,secondary_y=False),
        mpf.make_addplot(macd,panel=1,color='fuchsia',secondary_y=True),
        mpf.make_addplot(signal,panel=1,color='b',secondary_y=True),
       ]

s = mpf.make_mpf_style(base_mpf_style='classic',rc={'figure.facecolor':'lightgray'})

fig, axes = mpf.plot(df,type='candle',addplot=apds,figscale=1.5,figratio=(7,5),title='\n\nMACD',
                     style=s,volume=True,volume_panel=2,panel_ratios=(6,3,2),returnfig=True)

mpf.show()

mpf.make_addplot 支持添加任意图形到任意panel上,panel参数默认为0,如果设为1则将图形添加到第二个图上,color参数能设置图形颜色,secondary_y 能将图形的值设置到y轴上。效果如下:

此外,如果你希望能动态看到整个绘制过程,增加个animation即可:

# 公众号:二七阿尔量化
import pandas as pd
import mplfinance as mpf
import matplotlib.animation as animation

mins = pd.read_csv('sh300_1min.csv',index_col=0,parse_dates=True)
mins["day"] = pd.to_datetime(mins["day"])
mins = mins.set_index("day")
mins.index.name = 'Time'
candle_chart = mins.tail(240)

df = candle_chart

exp12     = df['close'].ewm(span=12, adjust=False).mean()
exp26     = df['close'].ewm(span=26, adjust=False).mean()
macd      = exp12 - exp26
signal    = macd.ewm(span=9, adjust=False).mean()
histogram = macd - signal

apds = [mpf.make_addplot(exp12,color='lime'),
        mpf.make_addplot(exp26,color='c'),
        mpf.make_addplot(histogram,type='bar',width=0.7,panel=1,
                         color='dimgray',alpha=1,secondary_y=False),
        mpf.make_addplot(macd,panel=1,color='fuchsia',secondary_y=True),
        mpf.make_addplot(signal,panel=1,color='b',secondary_y=True),
       ]

s = mpf.make_mpf_style(base_mpf_style='classic',rc={'figure.facecolor':'lightgray'})

fig, axes = mpf.plot(df,type='candle',addplot=apds,figscale=1.5,figratio=(7,5),title='\n\nMACD',
                     style=s,volume=True,volume_panel=2,panel_ratios=(6,3,2),returnfig=True)

mpf.show()

ax_main = axes[0]
ax_emav = ax_main
ax_hisg = axes[2]
ax_macd = axes[3]
ax_sign = ax_macd
ax_volu = axes[4]


def animate(ival):
    if (20+ival) > len(df):
        print('no more data to plot')
        ani.event_source.interval *= 3
        if ani.event_source.interval > 12000:
            exit()
        return
    data = df.iloc[0:(30+ival)]
    exp12     = data['close'].ewm(span=12, adjust=False).mean()
    exp26     = data['close'].ewm(span=26, adjust=False).mean()
    macd      = exp12 - exp26
    signal    = macd.ewm(span=9, adjust=False).mean()
    histogram = macd - signal
    apds = [mpf.make_addplot(exp12,color='lime',ax=ax_emav),
            mpf.make_addplot(exp26,color='c',ax=ax_emav),
            mpf.make_addplot(histogram,type='bar',width=0.7,
                             color='dimgray',alpha=1,ax=ax_hisg),
            mpf.make_addplot(macd,color='fuchsia',ax=ax_macd),
            mpf.make_addplot(signal,color='b',ax=ax_sign),
           ]

    for ax in axes:
        ax.clear()
    mpf.plot(data,type='candle',addplot=apds,ax=ax_main,volume=ax_volu)

ani = animation.FuncAnimation(fig,animate,interval=100)

mpf.show()

还有许多更有趣的玩法,你可以阅读mplfinance的examples学习更多的使用技巧:

https://github.com/matplotlib/mplfinance/tree/master/examples

本文的全部代码和数据包括mplfinance的examples都可以在【二七阿尔量化】公众号后台回复:mplfinance 下载。

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

教你如何在 Windows 下让崩溃的 Python 程序自动重启

我们用Python定时跑一些自动化程序的时候会出现程序崩溃的情况。此时如果你本人不在电脑面前,或者没有留意到程序的崩溃,没有及时重新拉起程序,会造成或大或小的损失。那么我们如何在 Windows 下让崩溃的 Python 程序自动重启呢?答案是通过 Supervisor-win.

本文将教你如何在 Windows 下使用 Supervisor-win 重新拉起崩溃的Python程序。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install supervisor-win

如果你出现 “DLL load failed: 找不到指定的程序” 的报错,请重新安装pywin32:

pip install pywin32==223

2.Windows Python程序自动重启的配置

接下来,你需要编写一个让你的Python程序自动运行,遇到报错自动重启的配置:

[program:cancel]
command=G:\\Anaconda3\\envs\\tdx_easytrader\\python.exe D://CODE//tdx_easytrader//dataserver.py
    
[supervisord]
nodaemon=true

[supervisorctl]

前两行就是你的程序运行命令,在上面的例子中,program: 后面的关键词是你自定义的程序名,我的Python位于 G:\Anaconda3\envs\tdx_easytrader\python.exe,我想要自重启的脚本位于 D://CODE//tdx_easytrader//dataserver.py

此外,后面的三行是必须配置的,按我的默认写法即可。

编写完成后将配置命名为 supervisord.conf 保存于任何地方,可以是项目目录下,也可以是一个重要的配置目录文件夹。

然后执行以下命令启动 supervisord:

supervisord -c D:\CODE\tdx_easytrader\supervisord.conf

注意 -c 参数后就是你的 supervisord.conf 的绝对路径。启动完毕显示:

2022-06-27 19:58:54,809 INFO process group added: 'cancel'
2022-06-27 19:58:54,810 INFO supervisord started with pid 28472
2022-06-27 19:58:54,815 INFO Spawned: 'cancel' with pid 27220
2022-06-27 19:58:55,830 INFO success: cancel entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)

意思是,supervisord 进程已经启动,pid为28472。我命名为cancel的Python进程也已经启动,pid为27220。我们在任务管理器中可以查看到这两个进程:

3.测试

接下来我们测试一下它能否自动重启,让我们强杀 27220 这个进程,观察终端:

2022-06-27 19:58:54,815 INFO Spawned: 'cancel' with pid 27220
2022-06-27 19:58:55,830 INFO success: cancel entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2022-06-27 20:02:58,077 INFO exited: cancel (exit status 1; not expected)
2022-06-27 20:02:58,590 INFO Spawned: 'cancel' with pid 16640
2022-06-27 20:02:59,603 INFO success: cancel entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)

可以看到, 20:02:58秒的时候 cancel 程序意外退出(exit status 1; not expected),然后supervisord重新帮我们拉起了一个cancel程序,pid为16640:

测试成功,程序成功自重启。

Supervisor不仅会把日志输出到终端中,在你运行命令的目录中,它还会生成supervisord.log, 这里面也保存了所有运行日志:

当然,在上方我们supervisord的配置里,你也能配置日志输出位置、最大大小、分片数量等:

[supervisord]
logfile = /tmp/supervisord.log
logfile_maxbytes = 50MB
logfile_backups=10
loglevel = info
pidfile = /tmp/supervisord.pid

Supervisord 还有许多其他的功能,有兴趣的同学可以访问他们官网查询:

http://supervisord.org/introduction.html

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

Cpca 这个Python神器能帮你自动识别文字中的省市区并绘图

在做NLP(自然语言处理)相关任务时,经常会遇到需要识别并提取省、城市、行政区的需求。虽然我们自己通过关键词表一个个查找也能实现提取目的,但是需要先搜集省市区关键词表,相对而言比较繁琐。

今天给大家介绍一个模块,你只需要把字符串传递给这个模块,他就能给你返回这个字符串内的省、市、区关键词,并能给你在图片上标注起来,它就是 Cpca 模块。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install cpca

注意,目前 cpca 模块仅支持Python3及以上版本。

在 windows 上可能会出现类似如下问题

Building wheel for pyahocorasick (setup.py) ... error

先去下载 Microsoft Visual C++ Build Tools 安装VC++构建工具,再重新 pip install cpca,即可解决问题

2.Cpca 基本使用

通过两行代码就能实现最基本的省市区提取:

# 公众号: Python 实用宝典
# 2022/06/23

import cpca

location_str = [
    "广东省深圳市福田区巴丁街深南中路1025号新城大厦1层",
    "特斯拉上海超级工厂是特斯拉汽车首座美国本土以外的超级工厂,位于中华人民共和国上海市。",
    "三星堆遗址位于中国四川省广汉市城西三星堆镇的鸭子河畔,属青铜时代文化遗址"
]
df = cpca.transform(location_str)
print(df)

效果如下:

     省     市     区                     地址  adcode
0  广东省   深圳市   福田区     巴丁街深南中路1025号新城大厦1层  440304
1  上海市  None  None                      。  310000
2  四川省   德阳市   广汉市  城西三星堆镇的鸭子河畔,属青铜时代文化遗址  510681

注意第三条的广汉市,cpca 不仅识别到了语句中的县级市广汉市,还能自动匹配到其代管市的德阳市,不得不说非常强大。

如果你想获知程序是从字符串的那个位置提取出省市区名的,可以添加一个 pos_sensitive=True 参数:

# 公众号: Python 实用宝典
# 2022/06/23

import cpca

location_str = [
    "广东省深圳市福田区巴丁街深南中路1025号新城大厦1层",
    "特斯拉上海超级工厂是特斯拉汽车首座美国本土以外的超级工厂,位于中华人民共和国上海市。",
    "三星堆遗址位于中国四川省广汉市城西三星堆镇的鸭子河畔,属青铜时代文化遗址"
]
df = cpca.transform(location_str, pos_sensitive=True)
print(df)

效果如下:

(base) G:\push\20220623>python 1.py
     省     市     区                     地址  adcode  省_pos  市_pos  区_pos
0  广东省   深圳市   福田区     巴丁街深南中路1025号新城大厦1层  440304      0      3      6
1  上海市  None  None                      。  310000     38     -1     -1
2  四川省   德阳市   广汉市  城西三星堆镇的鸭子河畔,属青铜时代文化遗址  510681      9     -1     12

它标记出了识别到省、市、区的关键位置(index),当然如果是德阳市这种特殊的识别会被标记为-1.

3.高级使用

它还可以从大段文本中批量识别多个地区:

# 公众号: Python 实用宝典
# 2022/06/23

import cpca

long_text = "对一个城市的评价总会包含个人的感情。如果你喜欢一个城市,很有可能是喜欢彼时彼地的自己。"\
    "在广州、香港读过书,工作过,在深圳买过房、短暂生活过,去北京出了几次差。"\
    "想重点比较一下广州、深圳和香港,顺带说一下北京。总的来说,觉得广州舒适、"\
    "香港精致、深圳年轻气氛好、北京大气又粗糙。答主目前选择了广州。"
df = cpca.transform_text_with_addrs(long_text, pos_sensitive=True)
print(df)

效果如下:

(base) G:\push\20220623>python 1.py
          省     市     区 地址  adcode  省_pos  市_pos  区_pos
0       广东省   广州市  None     440100     -1     44     -1
1   香港特别行政区  None  None     810000     47     -1     -1
2       广东省   深圳市  None     440300     -1     58     -1
3       北京市  None  None     110000     71     -1     -1
4       广东省   广州市  None     440100     -1     86     -1
5       广东省   深圳市  None     440300     -1     89     -1
6   香港特别行政区  None  None     810000     92     -1     -1
7       北京市  None  None     110000    100     -1     -1
8       广东省   广州市  None     440100     -1    110     -1
9   香港特别行政区  None  None     810000    115     -1     -1
10      广东省   深圳市  None     440300     -1    120     -1
11      北京市  None  None     110000    128     -1     -1
12      广东省   广州市  None     440100     -1    143     -1

不仅如此,模块中还自带一些简单绘图工具,可以在地图上将上面输出的数据以热力图的形式画出来:

# 公众号: Python 实用宝典
# 2022/06/23

import cpca
from cpca import drawer

long_text = "对一个城市的评价总会包含个人的感情。如果你喜欢一个城市,很有可能是喜欢彼时彼地的自己。"\
    "在广州、香港读过书,工作过,在深圳买过房、短暂生活过,去北京出了几次差。"\
    "想重点比较一下广州、深圳和香港,顺带说一下北京。总的来说,觉得广州舒适、"\
    "香港精致、深圳年轻气氛好、北京大气又粗糙。答主目前选择了广州。"
df = cpca.transform_text_with_addrs(long_text, pos_sensitive=True)
drawer.draw_locations(df[cpca._ADCODE], "df.html")

运行的时候可能会报这个错:

(base) G:\push\20220623>python 1.py
Traceback (most recent call last):
  File "1.py", line 12, in <module>
    drawer.draw_locations(df[cpca._ADCODE], "df.html")
  File "G:\Anaconda3\lib\site-packages\cpca\drawer.py", line 41, in draw_locations
    import folium
ModuleNotFoundError: No module named 'folium'

使用pip安装即可:

pip install folium

然后重新运行代码,会在当前目录下生成 df.html, 双击打开,效果如下:

怎么用,是不是感觉非常方便?以后地点的识别用这个模块就完全够了。

还有更多的细节你可以访问这个项目的Github主页阅读,该项目的README完全中文编写,非常容易阅读:

https://github.com/DQinYuan/chinese_province_city_area_mapper

如果你无法访问GitHub,也可以在Python实用宝典公众号后台回复:cpca 下载完整项目。

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

Empyrical 教你Python一行代码计算量化投资风险指标

Empyrical 是一个知名的金融风险指标库。它能够用于计算年平均回报、最大回撤、Alpha值、Beta值、卡尔马率、Omega率、夏普率等。它还被用于zipline和pyfolio,是Quantopian开发的三件套之一。

下面就教你如何使用 Empyrical 这个风险指标计算神器。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install empyrical

2. Empyrical 计算风险指标

计算最大回撤,你只需要从 empyrical 库中引入 max_drawdown ,将数据作为参数传入计算,一行代码就能实现:

import numpy as np
from empyrical import max_drawdown

returns = np.array([.01, .02, .03, -.4, -.06, -.02])

# 计算最大回撤
max_drawdown(returns)
# -0.4472800000000001

同样地,如果你需要计算alpha和beta指标:

import numpy as np
from empyrical import alpha_beta

returns = np.array([.01, .02, .03, -.4, -.06, -.02])
benchmark_returns = np.array([.02, .02, .03, -.35, -.05, -.01])

# 计算alpha和Beta值
alpha, beta = alpha_beta(returns, benchmark_returns)
print(alpha, beta)
# -0.7960672549836803 1.1243025418474892

如果你想要计算夏普率,同样也是一行代码就能解决,只不过你需要注意这几个参数的意义:

import numpy as np
from empyrical import sharpe_ratio

returns = np.array([.01, .02, .03, -.4, -.06, -.02])

# 计算夏普率
sr = sharpe_ratio(returns, risk_free=0, period='daily', annualization=None)
print(sr)
# -6.7377339531573535

各个参数的意义如下:

参数数据类型意义
returnspandas.Series策略的日回报,非累积。
risk_freeint, float本周期内的无风险利率
periodstr, optional确定回报数据的周期,默认为天。
annualizationint, optional交易日总数(用于计算年化)。如果是daily,则默认为252个交易日。

3.更多的指标

Empyrical 能提供使用的指标非常多,这里就不一一介绍了,基本上用法都和夏普率的计算方法差不多,这里介绍他们的方法和参数。

3.1 omega_ratio

empyrical.omega_ratio(returns, risk_free=0.0, required_return=0.0, annualization=252)
参数数据类型意义
returnspandas.Series策略的日回报,非累积。
risk_freeint, float本周期内的无风险利率
required_returnfloat, optional投资者可接受的最低回报。考虑正收益与负收益的阈值。它会被转为适应本周期回报的值。例如,可接受的最低年回报100会被转为最低0.018
annualizationint, optional交易日总数(用于计算年化)。如果是daily,则默认为252个交易日。

3.2 calmar_ratio

empyrical.calmar_ratio(returns, period='daily', annualization=None)
参数数据类型意义
returnspandas.Series策略的日回报,非累积。
periodstr, optional确定回报数据的周期,默认为天。
annualizationint, optional交易日总数(用于计算年化)。如果是daily,则默认为252个交易日。

3.3 sortino_ratio

empyrical.sortino_ratio(returns, required_return=0, period='daily', annualization=None, _downside_risk=None)
参数数据类型意义
returnspandas.Series策略的日回报,非累积。
required_returnfloat最小投资回报
periodstr, optional确定回报数据的周期,默认为天。
annualizationint, optional交易日总数(用于计算年化)。如果是daily,则默认为252个交易日。
_downside_riskfloat, optional给定输入的下跌风险。如果没有提供则自动计算

更多的指标及其说明,请查看empyrical源代码的stats.py文件,里面还包含了所有指标的计算逻辑,如果你想了解每个指标的计算方法,可以查看这个文件进行学习:

https://github.com/quantopian/empyrical/blob/master/empyrical/stats.py

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 通过阿里云日志服务上传日志并监控告警

在我们的日常生活工作中,经常会遇到需要上传日志的场景,比如多台机器运行同一个程序,并且需要记录每台机器程序产生的日志,根据相关关键词告警,或者进行无数据告警,如果自己搭建这套系统需要耗费不少时间,因此如果能使用市面上现成的系统会很方便。

本文将教你如何通过阿里云日志服务搭建一套通过Python上传日志、配置日志告警的监控服务。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install aliyun-log-python-sdk

接下来,登陆阿里云控制台,进入日志应用,通过下面的步骤创建日志Project和Logstore:

点击Python – SDK 写入,再根据你的需要创建Project和Logstore:

随后会进入这个页面,直接点击确定即可:

2.使用阿里云SDK上传Python日志

为了使用阿里云SDK上传日志,我们需要先获取Access Token, 将鼠标移动到右上角头像上点击AccessKey管理:

然后点击创建AccessKey,输入相关验证信息就能获取 accessKeyId 和 accessKey:

编写Python代码,配置AccessKey和你在第一步骤创建的Project及logstore名称:

from aliyun.log import LogClient, PutLogsRequest, LogItem, GetLogsRequest, IndexConfig
import time

# 配置AccessKey、服务入口、Project名称、Logstore名称等相关信息。
# 阿里云访问密钥AccessKey。更多信息,请参见访问密钥。
# 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维。
accessKeyId = "你的AccessKey ID"
accessKey = "你的AccessKey"
# 日志服务的域名。更多信息,请参见服务入口。此处以广州为例,其它地域请根据实际情况填写。
endpoint = "cn-guangzhou.log.aliyuncs.com"

# 创建日志服务Client。
client = LogClient(endpoint, accessKeyId, accessKey)

# Project名称。
project_name = "aliyun-test-project"
#Logstore名称
logstore_name = "aliyun-test-logstore"
# 查询语句。
query = "*| select dev,id from " + logstore_name
# from_time和to_time表示查询日志的时间范围,Unix时间戳格式。
from_time = int(time.time()) - 3600
to_time = time.time() + 3600

然后我们就可以编写Python代码创建索引(日志的索引可以理解为MySQL中的数据库)和插入日志了:

# 向Logstore写入数据。
def put_logs():
    print("ready to put logs for %s" % logstore_name)
    log_group = []
    for i in range(0, 100):
        log_item = LogItem()
        contents = [
            ('dev', 'test_put'),
            ('id', str(i))
        ]
        log_item.set_contents(contents)
        log_group.append(log_item)
    request = PutLogsRequest(project_name, logstore_name, "", "", log_group, compress=False)
    client.put_logs(request)
    print("put logs for %s success " % logstore_name)
    time.sleep(5)

if __name__ == '__main__':
    # 向Logstore写入数据。
    put_logs()

运行程序后出现对应的提示,说明日志上传成功:

python test.py
# ready to put logs for tradingview
# put logs for tradingview success 

进入控制台对应的Project,你会看到刚刚上传的日志已经显示在上面:

3.配置日志告警

日志告警的配置也非常简单,输入你的查询条件,获得输出后点击上方另存为告警:

在查询统计中添加你需要监控并触发告警的条件,比如我设置出现一次该日志的时候触发告警:

效果如下,我这里文本配置得太简单了,你也可以在标注中配置复杂一点的文本:

用起来挺方便的,如果你有类似的多机器日志监控服务,比如分布式模型训练监控、交易服务监控等等,可以考虑使用这个日志服务。

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python Pyintervals 解决你的阈值判断问题

Pyintervals 是一个用于数值区间计算的模块,比如我们想要判断一个数值是否处于一个、或者一系列区间范围内,就可以使用Pyintervals模块取缔IF-ELSE语句以达到简化代码的目的。

如果你想一次性生成上千个区间阈值并进行数值区间判断,比如根据数值生成成百上千个分类,那么这个模块就是你的最佳选择。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install pyinterval

2.Pyintervals 使用方法

使用Pyinterval做区间和阈值判断是非常简单的:

from interval import interval
a = interval[1,5]
# interval([1.0, 5.0])
print(3 in a)
# True

此外,你还可以构建一个多区间:

from interval import interval
a = interval([0, 1], [2, 3], [10, 15])
print(2.5 in a)
# True

interval.hall 方法还可以将多个区间合并,取其最小及最大值为边界:

from interval import interval
a = interval.hull((interval[1, 3], interval[10, 15], interval[16, 2222]))
# interval([1.0, 2222.0])
print(1231 in a)
# True

区间并集计算:

from interval import interval
a = interval.union([interval([1, 3], [4, 6]), interval([2, 5], 9)])
# interval([1.0, 6.0], [9.0])
print(5 in a)
# True
print(8 in a)
# False

3.生成多个阈值区间

如果你在做深度学习训练分类任务,你的分类数量比较多,达到了上百个,请不要傻傻地使用IF-ELSE, 下面教你使用四行代码生成上百个阈值区间。

假设你的值区间分布在0,1之间,每个阈值范围为0.005,并有正负两个方向。下面这4行代码就能非常简单地实现你想要的区间阈值:

from interval import interval
import numpy as np
threshold_list = np.arange(0.0, 1.0, 0.005)
intervals = [interval([threshold_list[i - 1], threshold_list[i]]) for i in range(1, len(threshold_list))]
intervals += [interval([-threshold_list[i], -threshold_list[i - 1]]) for i in range(len(threshold_list) - 1, 0, -1)]
print(len(intervals))
# 398
print(intervals[0], intervals[-1])
# interval([0.0, 0.005]) interval([-0.005, -0.0])

有了这个阈值,区间,你想要画分类就非常简单了,下面是一个简单示例,实际工作中要因不同应用场景改变使用方式。

target = 0.023
class_labels = {}
for index, interval_ in enumerate(intervals):
    if target in interval_:
        class_labels[target] = index

Pyintervals对于正在做大规模分类任务的同学而言是非常好用的模块,建议有需要的朋友可以试一试。其他同学也可以收藏点赞记录一下,说不定未来也会有应用场景呢!

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

Tsmoothie 这个神奇的Python库,可以将数据平滑化并找到异常点

在处理数据的时候,我们经常会遇到一些非连续的散点时间序列数据:

有些时候,这样的散点数据是不利于我们进行数据的聚类和预测的。因此我们需要把它们平滑化,如下图所示:

将散点都去除,平滑后的效果如下:

​这样的时序数据是不是看起来舒服多了?​此外,使用平滑后的时序数据去做聚类或预测或许有令人惊艳的效果,因为它去除了一些偏差值并细化了数据的分布范围。

如果我们自己开发一个这样的平滑工具,会耗费不少的时间。​因为平滑的技术有很多种,你需要一个个地去研究,找到最合适的技术并编写代码,这是一个非常耗时的过程。平滑技术包括但不限于:

  • 指数平滑
  • 具有各种窗口类型(常数、汉宁、汉明、巴特利特、布莱克曼)的卷积平滑
  • 傅立叶变换的频谱平滑
  • 多项式平滑
  • 各种样条平滑(线性、三次、自然三次)
  • 高斯平滑
  • 二进制平滑

所幸,有大佬已经为我们实现好了时间序列的这些平滑技术,并在GitHub上开源了这份模块的代码——它就是 tsmoothie。

下面就让我们来试一下 tsmoothie.

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install tsmoothie

PS, Tsmoothie仅支持Python 3.6 及以上的版本。

2.Tsmoothie 基本使用

为了尝试Tsmoothie的效果,我们需要生成随机数据:

import numpy as np
import matplotlib.pyplot as plt
from tsmoothie.utils_func import sim_randomwalk
from tsmoothie.smoother import LowessSmoother

# 生成 3 个长度为200的随机数据组
np.random.seed(123)
data = sim_randomwalk(n_series=3, timesteps=200, 
                      process_noise=10, measure_noise=30)

然后使用Tsmoothie执行平滑化:

# 平滑
smoother = LowessSmoother(smooth_fraction=0.1, iterations=1)
smoother.smooth(data)

通过 smoother.smooth_data 你就可以获取平滑后的数据:

print(smoother.smooth_data)
# [[   5.21462928    3.07898076    0.93933646   -1.19847767   -3.32294934 
#     -5.40678762   -7.42425709   -9.36150892  -11.23591897  -13.05271523 
#      .......       .......       .......      .......       .......   ]]

绘制效果图:

# 生成范围区间
low, up = smoother.get_intervals('prediction_interval')

plt.figure(figsize=(18,5))

for i in range(3):
    
    plt.subplot(1,3,i+1)
    plt.plot(smoother.smooth_data[i], linewidth=3, color='blue')
    plt.plot(smoother.data[i], '.k')
    plt.title(f"timeseries {i+1}"); plt.xlabel('time')

    plt.fill_between(range(len(smoother.data[i])), low[i], up[i], alpha=0.3)

3.基于Tsmoothie的极端异常值检测

事实上,基于smoother生成的范围区域,我们可以进行异常值的检测:

可以看到,在蓝色范围以外的点,都属于异常值。我们可以轻易地将这些异常值标红或记录,以便后续的处理。

_low, _up = smoother.get_intervals('sigma_interval', n_sigma=2)
series['low'] = np.hstack([series['low'], _low[:,[-1]]])
series['up'] = np.hstack([series['up'], _up[:,[-1]]])
is_anomaly = np.logical_or(
    series['original'][:,-1] > series['up'][:,-1], 
    series['original'][:,-1] < series['low'][:,-1]
).reshape(-1,1)

假设蓝色范围interval的最大值为up、最小值为low,如果存在 data > up 或 data < low 则表明此数据是异常点。

使用以下代码通过滚动数据点进行平滑化和异常检测,就能保存得到上方的GIF动图。

# https://github.com/cerlymarco/MEDIUM_NoteBook/blob/master/Anomaly_Detection_RealTime/Anomaly_Detection_RealTime.ipynb

import numpy as np
import matplotlib.pyplot as plt
from celluloid import Camera
from collections import defaultdict
from functools import partial
from tqdm import tqdm

from tsmoothie.utils_func import sim_randomwalk, sim_seasonal_data
from tsmoothie.smoother import *


def plot_history(ax, i, is_anomaly, window_len, color='blue', **pltargs):
    
    posrange = np.arange(0,i)
    
    ax.fill_between(posrange[window_len:], 
                    pltargs['low'][1:], pltargs['up'][1:], 
                    color=color, alpha=0.2)
    if is_anomaly:
        ax.scatter(i-1, pltargs['original'][-1], c='red')
    else:
        ax.scatter(i-1, pltargs['original'][-1], c='black')
    ax.scatter(i-1, pltargs['smooth'][-1], c=color)
    
    ax.plot(posrange, pltargs['original'][1:], '.k')
    ax.plot(posrange[window_len:], 
            pltargs['smooth'][1:], color=color, linewidth=3)
    
    if 'ano_id' in pltargs.keys():
        if pltargs['ano_id'].sum()>0:
            not_zeros = pltargs['ano_id'][pltargs['ano_id']!=0] -1
            ax.scatter(not_zeros, pltargs['original'][1:][not_zeros], 
                       c='red', alpha=1.)

np.random.seed(42)

n_series, timesteps = 3, 200

data = sim_randomwalk(n_series=n_series, timesteps=timesteps, 
                      process_noise=10, measure_noise=30)

window_len = 20

fig = plt.figure(figsize=(18,10))
camera = Camera(fig)

axes = [plt.subplot(n_series,1,ax+1) for ax in range(n_series)]
series = defaultdict(partial(np.ndarray, shape=(n_series,1), dtype='float32'))

for i in tqdm(range(timesteps+1), total=(timesteps+1)):
    
    if i>window_len:
    
        smoother = ConvolutionSmoother(window_len=window_len, window_type='ones')
        smoother.smooth(series['original'][:,-window_len:])

        series['smooth'] = np.hstack([series['smooth'], smoother.smooth_data[:,[-1]]]) 

        _low, _up = smoother.get_intervals('sigma_interval', n_sigma=2)
        series['low'] = np.hstack([series['low'], _low[:,[-1]]])
        series['up'] = np.hstack([series['up'], _up[:,[-1]]])

        is_anomaly = np.logical_or(
            series['original'][:,-1] > series['up'][:,-1], 
            series['original'][:,-1] < series['low'][:,-1]
        ).reshape(-1,1)
        
        if is_anomaly.any():
            series['ano_id'] = np.hstack([series['ano_id'], is_anomaly*i]).astype(int)
            
        for s in range(n_series):
            pltargs = {k:v[s,:] for k,v in series.items()}
            plot_history(axes[s], i, is_anomaly[s], window_len, 
                         **pltargs)

        camera.snap()
        
    if i>=timesteps:
        continue
    
    series['original'] = np.hstack([series['original'], data[:,[i]]])

    
print('CREATING GIF...')  # it may take a few seconds
camera._photos = [camera._photos[-1]] + camera._photos
animation = camera.animate()
animation.save('animation1.gif', codec="gif", writer='imagemagick')
plt.close(fig)
print('DONE')

注意,异常点并非都是负面作用,在不同的应用场景下,它们可能代表了不同的意义。

比如在股票中,它或许可以代表着震荡行情中某种趋势反转的信号。

或者在家庭用电量分析中,它可能代表着某个时刻的用电峰值,根据这个峰值我们可以此时此刻开启了什么样的电器。

所以异常点的作用需要根据不同应用场景进行不同的分析,才能找到它真正的价值。

总而言之,Tsmoothie 不仅可以使用多种平滑技术平滑化我们的时序数据,还可以根据平滑结果找出数据中的离群点,是我们做数据分析和研究的一个好帮手,非常有价值。

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

Asciinema – 终端日志记录神器,机器学习开发者的福音

我们在做机器学习/深度学习开发的时候,经常会产生如下所示的大量日志:

这些日志如果不保存,转瞬即逝,当我们想要回去翻看某一轮训练日志的时候,会很遗憾的发现找不到了。

现在有了这个 Asciinema 这个神器,我们不仅能找到当时的终端日志导出,还能够“重播日志”并“分享日志”。非常牛逼:

Asciinema 是使用Python开发的工具,请按下面的流程安装并使用。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install asciinema

2.Asciinema 使用方法

终端输入如下命令,记录你的第一个终端日志:

asciinema rec first.cast

输入完成后会显示如下的提示:

(gs3_9) zjr@sgd-linux-1:~/cnn_test$ asciinema rec first.cast
  
asciinema: recording asciicast to first.cast
asciinema: press <ctrl-d> or type "exit" when you're done

意思就是日志会被保存在当前文件夹下的first.cast,如果你想结束录制,按 Ctrl + D 即可。

记录完毕后,以双倍速度重播该日志:

asciinema play -s 2 first.cast

或以正常速度但空闲时间限制为 2 秒:

asciinema play -i 2 first.cast

你也可以在启动终端日志录制时传递 -i 2 asciinema rec,将其永久设置在录制中:

asciinema rec first.cast -i 2

空闲时间的限制使录制更有趣。试试吧。

如果你想在网络上观看和分享,请上传:

asciinema upload first.cast

这个命令会将日志记录上传到 asciinema.org,此外,它会打印一个秘密链接,你可以使用该链接在网络浏览器中观看你录制的终端日志:

你可以通过省略文件名一步录制和上传终端的日志:

asciinema rec

录制完成后,系统会要求你确认上传。未经你的同意,不会向任何地方发送任何内容。

3.播放日志

查看日志有四种方式,最普通的是通过本地文件进行终端重播:

asciinema play /path/to/asciicast.cast

以下键盘快捷键可用:

  • Space– 暂停,
  • .– 按帧步进(暂停时),
  • Ctrl+C– 退出

第二种方式是通过url播放:

asciinema play https://asciinema.org/a/22124.cast
asciinema play http://example.com/demo.cast

这个方式需要你的日志已经上传到asciinema.org中。

第三种方式是通过你自己生成的html页面访问(需要<link rel="alternate" type="application/x-asciicast" href="/my/ascii.cast">在页面的 HTML 中):

asciinema play http://your_html_path/post.html

第四种方式是通过标准输入输出播放:

cat /path/to/asciicast.cast | asciinema play -
ssh user@host cat asciicast.cast | asciinema play -

可用选项:

  • -i, --idle-time-limit=<sec>– 将重播的终端空闲不动时间闲置为最大<sec>秒数
  • -s, --speed=<factor>– 播放速度

4.导出日志

导出终端日志到文本文件非常简单:

asciinema cat existing.cast > terminal_output.txt

所有的终端日志都会被导出到 terminal_output.txt 中,非常方便好用。

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

超级安全!Python Pillow合成多张图片到PDF格式

在日常生活中,经常会遇到需要提交身份证正反面证明资料的情况,而且这些网站大部分只接受pdf格式,这时候我们就需要把身份证正反面两张图片合成为一个pdf文件。

在macOS系统下,预览软件可以轻松做到这一点,同时打开图片到一个预览窗口下,点击导出PDF就能成功导出。但是Windows系统就没有这么方便的软件可以实现这一点,网上有很多合成PDF的网站,但是这些网站无一例外需要上传PDF进行合成,个人认为非常地不安全。

因此,最安全的方法,还是我们自己写一个Python脚本实现合成功能。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install pillow

2.Pillow 合成PDF原理

Pillow模块,即PIL:Python Imaging Library,已经是Python平台事实上的图像处理标准库了。PIL功能非常强大,但API却非常简单易用。通过它,我们能很轻松地操作图像,并导出为不同格式。

首先来一个简单的示例,我们将打开一张图片,并将其保存为pdf格式:

from PIL import Image
import os


def convert_img_pdf(filepath, output_path):
    """
    转换图片为pdf格式

    Args:
        filepath (str): 文件路径
        output_path (str): 输出路径
    """
    output = Image.open(filepath)
    output.save(output_path, "pdf", save_all=True)
    
    
if __name__ == "__main__":
    convert_img_pdf("1.jpeg", "./test.pdf")

随便使用一张图片测试一下:

在运行代码后,它便成功地转化为了PDF文件:

几行代码便完成了这个转换,这个可比那些把照片上传到云端的网站安全多了。

3.多张照片合成PDF

有了前面照片转化PDF的基础知识,想要理解下面的多图合成PDF的代码就非常简单了。

其实就是使用了.save的一个特殊参数 append_images:

output.save(pdfFilePath, "pdf", save_all=True, append_images=sources)

通过把图片都存入到一个”sources”数组中,我们就能很轻易地合成这些图像到PDF中。

from PIL import Image
import os

def combine_imgs_pdf(folder_path, pdf_file_path):
    """
    合成文件夹下的所有图片为pdf

    Args:
        folder_path (str): 源文件夹
        pdf_file_path (str): 输出路径
    """
    files = os.listdir(folder_path)
    png_files = []
    sources = []
    for file in files:
        if 'png' in file or 'jpg' in file:
            png_files.append(folder_path + file)
    png_files.sort()

    output = Image.open(png_files[0])
    png_files.pop(0)
    for file in png_files:
        png_file = Image.open(file)
        if png_file.mode == "RGB":
            png_file = png_file.convert("RGB")
        sources.append(png_file)
    output.save(pdf_file_path, "pdf", save_all=True, append_images=sources)

if __name__ == "__main__":
    folder = r"G:\证件\\"
    pdfFile = r"G:\证件\身份证.pdf"
    combine_imgs_pdf(folder, pdfFile)

这样,只要将你的证件照都放在一个文件夹中,运行这个Python代码,它就能自动将这些证件合成到一个PDF中,并输出到你指定的路径。非常简单方便。

有需要的小伙伴,刚开那这份代码去试一下吧!在Python实用宝典后台回复 合成pdf 就能下载啦!

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python超好用的命令行参数工具—Click

Click 是一个简洁好用的Python模块,它能用尽量少的代码实现漂亮的命令行界面。它不仅开箱即用、还能支持高度自定义的配置。

一个简单的示例如下:

import click

@click.command()
@click.option('--count', default=1, help='Number of greetings.')
@click.option('--name', prompt='Your name',
              help='The person to greet.')
def hello(count, name):
    """Simple program that greets NAME for a total of COUNT times."""
    for x in range(count):
        click.echo(f"Hello {name}!")

if __name__ == '__main__':
    hello()

效果如下:

可见这个模块的强大之处,你只需要在对应的函数上加几个装饰器,就能实现带提示符的命令行界面的创建,相当方便。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install click

2.基本使用

如文首所示的例子一样,@click.option 是最基本的选项,它既可以设定参数默认值,也可以设定必须传入参数:

@click.command()
@click.option('--n', default=1) # 设定了默认值
def dots(n):
    click.echo('.' * n)
    

@click.command()
@click.option('--n', required=True, type=int) # 设定必须传入参数值
def dots(n):
    click.echo('.' * n)

如果你设置了必须传入相关参数,那么在没传入参数的情况下,效果是这样的:

当然,它还支持设定多种参数别名,比如下面的 –from 和 -f 是等效的:

@click.command()
@click.option('--from', '-f', 'from_')
@click.option('--to', '-t')
def reserved_param_name(from_, to):
    click.echo(f"from {from_} to {to}")

3.多值参数

如果你的选项需要多个参数,Click也能帮你实现这个需求。

@click.command()
@click.option('--pos', nargs=2, type=float)
def findme(pos):
    a, b = pos
    click.echo(f"{a} / {b}")

可见,通过配置nargs参数,你可以将用户传递的值存入元组,并在代码中解包这个元组拿到所有的值。

效果如下:

你还可以配置一个参数叫 multiple,这个参数可以让你接受N个值:

@click.command()
@click.option('--message', '-m', multiple=True)
def commit(message):
    click.echo(' '.join(message))

效果如下:

4.其他功能

你还可以使用Click来计数,这个使用非常罕见:

@click.command()
@click.option('-v', '--verbose', count=True)
def log(verbose):
    click.echo(f"Verbosity: {verbose}")

效果如下:

布尔标志

此外,Click还带有布尔标志功能,你可以直接使用 “/” 来标志参数为二选一参数,函数中直接就会拿到布尔型的变量:

import sys

@click.command()
@click.option('--shout/--no-shout', default=False)
def info(shout):
    rv = sys.platform
    if shout:
        rv = rv.upper() + '!!!!111'
    click.echo(rv)

效果如下:

选择选项

你可以直接限定用户的输入范围:

@click.command()
@click.option('--hash-type',
              type=click.Choice(['MD5', 'SHA1'], case_sensitive=False))
def digest(hash_type):
    click.echo(hash_type)

提示文本

在文首提到的例子中,输出了个 “You name:” 的提示,其实是 option 中的prompt参数控制的:

@click.command()
@click.option('--name', prompt='Your name please')
def hello(name):
    click.echo(f"Hello {name}!")

好了,Click的功能就介绍到这里,他还有许多高级的用法,比如动态默认值、回调函数等等,大家可以通过官方文档了解这些高级功能的使用方法:

https://click.palletsprojects.com/en/8.0.x/options/#name-your-options

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典