Python编程笔记(持续更新...)

python编程笔记

**注:内容大部分来自平时从网络摘抄,如有侵权非常抱歉,请联系weixin:470770753**

  • Python调用exe并输入信息
# -*- `coding: utf-8 -*-
import subprocess
p = subprocess.Popen("t1.exe",shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
cm='12\n'
o,e=p.communicate(cm.encode("utf-8"))
print(o)

  • Pythhon计算时间戳
#计算当天当下时间戳与特定时间戳的差
class TimeStampDif():
    def dif(self,str):
        time_str=time.strftime("%Y-%m-%d", time.localtime())+' '+str
        time_stamp=time.mktime(time.strptime(time_str, "%Y-%m-%d %H:%M:%S"))
 
        return time.time()-time_stamp

  • Python将字符串作为代码运行

1.exec()将字符串作为代码运行

exec("print('hello,world')")
>>hello,world

2.exec函数主要用于动态地创建代码字符串。如果这种字符串来自其他地方,就几乎无法确定它将包含什么内容。因此为了安全起见,要提供一个字典以充当命名空间。
命名空间:可以视为一个放置变量的地方,类似于一个看不见的字典。因此,当你执行语句x=1时,将在当前命名空间存储键x和值1。当前命名空间通常是全局命名空间,但也并非必然如此。

from math import sqrt
scope={}
exec('sqrt=1',scope)
sqrt(4)
>>2.0
scope['sqrt']
>>1

如此可见,可能带来破坏的代码并非覆盖函数sqrt。sqrt函数该怎样还怎样,而通过exec执行赋值语句创建的变量位于scope中。

  1. eval()
    eval是一个类似于exec的内置函数。
    exec执行一系列Python语句,而eval计算用字符串表示的Python表达式的值,并返回结果。(exec什么都不返回,因为它本身是条语句)
    与exec一样,也可以向eval提供一个命名空间。
eval(input("input an expression:"))
>input an expression:4+8
>12

  • 使用cython入门,编译pyd文件
    python3使用cython入门,编译pyd文件,加速100倍!

一、安装cython 和 Visiual Studio 2015 和一些设置
1.安装 Visiual Studio 2015
https://www.cnblogs.com/jianmu/p/7497274.html?utm_source=debugrun&utm_medium=referral
2.安装 cython:
pip install Cython

二、编写测试代码

1.新建test.py文件,编写斐波那契数列测试代码
https://www.cnblogs.com/yafengabc/p/6130849.html

import time


def fib(n):
    if n == 0:
        return 0
    if n == 1:
        return 1
    return fib(n - 1) + fib(n - 2)


def get_time():
    t = time.time()
    fib(40)
    return time.time() - t

print(get_time())

运行,输出的结果为40秒左右
2.将test.py复制一个 重命名为 test.pyx (这两个文件没有关联,而因为最后生成的pyd文件导入优先级高于py文件,所以py文件不用移除),给变量加上静态类型声明。

import time

cdef int fib(int n):
    if n == 0:
        return 0
    if n == 1:
       return 1
    return fib(n - 1) + fib(n - 2)

def get_time():
    t = time.time()
    fib(40)
    return time.time() - t

3.开始编译
https://www.cnblogs.com/jianmu/p/7497274.html?utm_source=debugrun&utm_medium=referral
在同目录下新建setup.py (名称随意),内容如下:
from distutils.core import setup
from Cython.Build import cythonize

setup(ext_modules = cythonize(“test.pyx”))
控制台进入该目录,执行 python setup.py build_ext (加上–inplace参数后生成的目录结构会稍稍不同,但是没有影响),最后生成了一大堆文件,其中的pyd文件是我们所需要的,其他的可以删除。
将pyd文件的名称更改为test.pyd,这时候 test.pyx 也已经完成了他的使命。注意,pyd的名称似乎必须与之前的pyx名称相同,否则会提示如下错误:
ImportError: dynamic module does not define module export function

4.测试编译后的代码的执行效率
新建一个包 pack_test,在包内新建一个 test_result.py,同时把test.pyd 文件也拷贝到这个包里。
test_result.py的内容如下:
import pack_test.test
print(pack_test.test.get_time())
输出结果为0.42685914039611816, 速度提升了100倍左右!

三、一些其他的注意事项
https://www.jianshu.com/p/fc5025094912

1.pyx中用cdef定义的类型,除类以外对.py都不可见
2.。。。

四、cython代码优化工具

1.https://www.douban.com/group/topic/20950369/
2.http://www.cnblogs.com/xybaby/p/6510941.html
。。。

五、maya相关的一些资料

1.Python 2.7 cython cythonize py 编译成 pyd 谈谈那些坑 http://www.cnblogs.com/ibingshan/p/10334471.html
2.Maya mayapy.exe 安装 Cython,编译 pyd
https://www.cnblogs.com/ibingshan/p/10346354.html
。。。

六、可以用pyinstaller打包pyd文件

七、打包多个py文件为一个pyd文件
https://。。。/questions/19646985/making-one-pyd-for-a-set-of-files-with-cython
。。。=stackoverflow.com
packageA.pyx

include “mod1.pyx”
include “mod2.pyx”
include “mod3.pyx”

setup.py

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
setup(
    cmdclass = {'build_ext': build_ext},
    ext_modules = [
        Extension("packageA", sources=["packageA.pyx"])
    ]
)

  • 详解利用Python scipy.signal.filtfilt() 实现信号滤波

这篇文章主要介绍了详解利用Python scipy.signal.filtfilt() 实现信号滤波,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧本文将以实战的形式基于scipy模块使用Python实现简单滤波处理,包括内容有1.低通滤波,2.高通滤波,3.带通滤波,4.带阻滤波器。具体的含义大家可以查阅大学课程,信号与系统。简单的理解就是低通滤波指的是去除高于某一阈值频率的信号;高通滤波去除低于某一频率的信号;带通滤波指的是类似低通高通的结合保留中间频率信号;带阻滤波也是低通高通的结合只是过滤掉的是中间部分。上面所说的内容会在实战部分加以介绍,可以对比理解一下。
如何实现的呢?我的理解,是通过时域转换为频域,在频域信号中去除相应频域信号,最后在逆转换还原为时域型号。具体的内容还是要查阅大学课程,信号与系统。自己学的很一般就不班门弄斧了。
有什么作用呢?My Opinions,可以消除一些干扰信号,以低通滤波为例,例如我们如果只是统计脉搏信号波形,应该在1Hz左右,却发现波形信号上有很多噪音,这些噪音都是成百上千Hz的,这些对于脉搏信号波形就属于无用的噪音,我们就可以通过低通滤波器将超出某一阈值的信号过滤掉,此时得到的波形就会比较平滑了。
在使用Python进行信号处理过程中,利用 scipy.signal.filtfilt()可以快速帮助实现信号的滤波。
1.函数的介绍
(1).滤波函数
scipy.signal.filtfilt(b, a, x, axis=-1, padtype=‘odd’, padlen=None, method=‘pad’, irlen=None)
输入参数:
b: 滤波器的分子系数向量
a: 滤波器的分母系数向量
x: 要过滤的数据数组。(array型)
axis: 指定要过滤的数据数组x的轴
padtype: 必须是“奇数”、“偶数”、“常数”或“无”。这决定了用于过滤器应用的填充信号的扩展类型。{‘odd’, ‘even’, ‘constant’, None}
padlen:在应用滤波器之前在轴两端延伸X的元素数目。此值必须小于要滤波元素个数- 1。(int型或None)
method:确定处理信号边缘的方法。当method为“pad”时,填充信号;填充类型padtype和padlen决定,irlen被忽略。当method为“gust”时,使用古斯塔夫森方法,而忽略padtype和padlen。{“pad” ,“gust”}
irlen:当method为“gust”时,irlen指定滤波器的脉冲响应的长度。如果irlen是None,则脉冲响应的任何部分都被忽略。对于长信号,指定irlen可以显著改善滤波器的性能。(int型或None)
输出参数:
y:滤波后的数据数组
(2).滤波器构造函数(仅介绍Butterworth滤波器)
scipy.signal.butter(N, Wn, btype=‘low’, analog=False, output=‘ba’)
输入参数:
N:滤波器的阶数
Wn:归一化截止频率。计算公式Wn=2截止频率/采样频率。(注意:根据采样定理,采样频率要大于两倍的信号本身最大的频率,才能还原信号。截止频率一定小于信号本身最大的频率,所以Wn一定在0和1之间)。当构造带通滤波器或者带阻滤波器时,Wn为长度为2的列表。
btype : 滤波器类型{‘lowpass’, ‘highpass’, ‘bandpass’, ‘bandstop’},
output : 输出类型{‘ba’, ‘zpk’, ‘sos’},
输出参数:
b,a: IIR滤波器的分子(b)和分母(a)多项式系数向量。output=‘ba’
z,p,k: IIR滤波器传递函数的零点、极点和系统增益. output= ‘zpk’
sos: IIR滤波器的二阶截面表示。output= ‘sos’
2.函数的使用
信号滤波中最常用的无非低通滤波、高通滤波和带通滤波。下面简单介绍这三种滤波的使用过程:
(1).高通滤波
#这里假设采样频率为1000hz,信号本身最大的频率为500hz,要滤除10hz以下频率成分,即截至频率为10hz,则wn=2
10/1000=0.02

from scipy import signal
 
b, a = signal.butter(8, 0.02, 'highpass')
filtedData = signal.filtfilt(b, a, data)#data为要过滤的信号

(2).低通滤波
#这里假设采样频率为1000hz,信号本身最大的频率为500hz,要滤除10hz以上频率成分,即截至频率为10hz,则wn=2*10/1000=0.02

from scipy import signal
 
b, a = signal.butter(8, 0.02, 'lowpass')
filtedData = signal.filtfilt(b, a, data)    #data为要过滤的信号

(3).带通滤波
#这里假设采样频率为1000hz,信号本身最大的频率为500hz,要滤除10hz以下和400hz以上频率成分,即截至频率为10hz和400hz,则wn1=210/1000=0.02,wn2=2400/1000=0.8。Wn=[0.02,0.8]

from scipy import signal
 
b, a = signal.butter(8, [0.02,0.8], 'bandpass')
filtedData = signal.filtfilt(b, a, data)  #data为要过滤的信号

参考:
1.https://docs.scipy.org/doc/scipy-0.18.1/reference/generated/scipy.signal.filtfilt.html
2.https://docs.scipy.org/doc/scipy-0.18.1/reference/generated/scipy.signal.butter.html#scipy.signal.butter

`

scipy.signal.filtfilt#

scipy.signal. filtfilt ( b, a, x, axis=- 1, padtype='odd', padlen=None, method='pad', irlen=None ) [source] #

Apply a digital filter forward and backward to a signal.

This function applies a linear digital filter twice, once forward and once backwards. The combined filter has zero phase and a filter order twice that of the original.

The function provides options for handling the edges of the signal.

The function sosfiltfilt (and filter design using output='sos') should be preferred over filtfilt for most filtering tasks, as second-order sections have fewer numerical problems.

Parameters
b (N,) array_like

The numerator coefficient vector of the filter.

a (N,) array_like

The denominator coefficient vector of the filter. If a[0] is not 1, then both a and b are normalized by a[0].

x array_like

The array of data to be filtered.

axis int, optional

The axis of x to which the filter is applied. Default is -1.

padtype str or None, optional

Must be ‘odd’, ‘even’, ‘constant’, or None. This determines the type of extension to use for the padded signal to which the filter is applied. If padtype is None, no padding is used. The default is ‘odd’.

padlen int or None, optional

The number of elements by which to extend x at both ends of axis before applying the filter. This value must be less than x.shape[axis] - 1. padlen=0 implies no padding. The default value is 3 * max(len(a), len(b)).

method str, optional

Determines the method for handling the edges of the signal, either “pad” or “gust”. When method is “pad”, the signal is padded; the type of padding is determined by padtype and padlen, and irlen is ignored. When method is “gust”, Gustafsson’s method is used, and padtype and padlen are ignored.

irlen int or None, optional

When method is “gust”, irlen specifies the length of the impulse response of the filter. If irlen is None, no part of the impulse response is ignored. For a long signal, specifying irlen can significantly improve the performance of the filter.

Returns
y ndarray

The filtered output with the same shape as x.

Notes

When method is “pad”, the function pads the data along the given axis in one of three ways: odd, even or constant. The odd and even extensions have the corresponding symmetry about the end point of the data. The constant extension extends the data with the values at the end points. On both the forward and backward passes, the initial condition of the filter is found by using lfilter_zi and scaling it by the end point of the extended data.

When method is “gust”, Gustafsson’s method [1] is used. Initial conditions are chosen for the forward and backward passes so that the forward-backward filter gives the same result as the backward-forward filter.

The option to use Gustaffson’s method was added in scipy version 0.16.0.

References

1

F. Gustaffson, “Determining the initial states in forward-backward filtering”, Transactions on Signal Processing, Vol. 46, pp. 988-992, 1996.

Examples

The examples will use several functions from scipy.signal.

>>> from scipy import signal
>>> import matplotlib.pyplot as plt

First we create a one second signal that is the sum of two pure sine waves, with frequencies 5 Hz and 250 Hz, sampled at 2000 Hz.

>>> t = np.linspace(0, 1.0, 2001)
>>> xlow = np.sin(2 * np.pi * 5 * t)
>>> xhigh = np.sin(2 * np.pi * 250 * t)
>>> x = xlow + xhigh

Now create a lowpass Butterworth filter with a cutoff of 0.125 times the Nyquist frequency, or 125 Hz, and apply it to x with filtfilt. The result should be approximately xlow, with no phase shift.

>>> b, a = signal.butter(8, 0.125)
>>> y = signal.filtfilt(b, a, x, padlen=150)
>>> np.abs(y - xlow).max()
9.1086182074789912e-06

We get a fairly clean result for this artificial example because the odd extension is exact, and with the moderately long padding, the filter’s transients have dissipated by the time the actual data is reached. In general, transient effects at the edges are unavoidable.

The following example demonstrates the option method="gust".

First, create a filter.

>>> b, a = signal.ellip(4, 0.01, 120, 0.125)  # Filter to be applied.

sig is a random input signal to be filtered.

>>> rng = np.random.default_rng()
>>> n = 60
>>> sig = rng.standard_normal(n)**3 + 3*rng.standard_normal(n).cumsum()

Apply filtfilt to sig, once using the Gustafsson method, and once using padding, and plot the results for comparison.

>>> fgust = signal.filtfilt(b, a, sig, method="gust")
>>> fpad = signal.filtfilt(b, a, sig, padlen=50)
>>> plt.plot(sig, 'k-', label='input')
>>> plt.plot(fgust, 'b-', linewidth=4, label='gust')
>>> plt.plot(fpad, 'c-', linewidth=1.5, label='pad')
>>> plt.legend(loc='best')
>>> plt.show()
../../_images/scipy-signal-filtfilt-1_00_00.png

The irlen argument can be used to improve the performance of Gustafsson’s method.

Estimate the impulse response length of the filter.

>>> z, p, k = signal.tf2zpk(b, a)
>>> eps = 1e-9
>>> r = np.max(np.abs(p))
>>> approx_impulse_len = int(np.ceil(np.log(eps) / np.log(r)))
>>> approx_impulse_len
137

Apply the filter to a longer signal, with and without the irlen argument. The difference between y1 and y2 is small. For long signals, using irlen gives a significant performance improvement.

>>> x = rng.standard_normal(5000)
>>> y1 = signal.filtfilt(b, a, x, method='gust')
>>> y2 = signal.filtfilt(b, a, x, method='gust', irlen=approx_impulse_len)
>>> print(np.max(np.abs(y1 - y2)))
1.80056858312e-10

  • matplotlib动态刷新
from matplotlib import pyplot as plt
import numpy as np
 
y = []
while True:
    y.append(np.random.randint(0,10))
    plt.clf()
    plt.plot(y)
    print(y)
    plt.pause(1)
    if len(y)>10:
        del y[0]

  • Python正态分布
    Python Scipy.stats 用法 | rvs pdf pmf用法

scipy.stats #生成指定分布
scipy.stats.poisson.rvs(loc=期望, scale=标准差, size=生成随机数的个数) #从泊松分布中生成指定个数的随机数

正态分布在x处的概率密度函数的函数值f(x)
scipy.stats.norm.pdf(x, loc=期望, scale=标准差)
scipy.stats.norm.pmf(x, loc=期望, scale=标准差) #pdf目前改为pmf

stats连续型随机变量的公共方法

名称:备注
rvs:产生服从指定分布的随机数
pdf:概率密度函数
cdf:累计分布函数 norm.cdf(1.6448536269514722)点位为1.645的概率分布
sf:残存函数(1-CDF)
ppf:分位点函数(CDF的逆)(参数是从左到右,总密度之和)norm.ppf(0.95)从左边开始百分之95%的分布位置
isf:逆残存函数(sf的逆)
fit:对一组随机取样进行拟合,最大似然估计方法找出最适合取样数据的概率密度函数系数。
*离散分布的简单方法大多数与连续分布很类似,但是pdf被更换为密度函数pmf。

常见分布 stats.

名称:含义
beta:beta分布
f:F分布
gamma:gam分布
poisson:泊松分布
hypergeom:超几何分布
lognorm:对数正态分布
binom:二项分布
uniform:均匀分布
chi2:卡方分布
cauchy:柯西分布
laplace:拉普拉斯分布
rayleigh:瑞利分布
t:学生T分布
norm:正态分布
expon:指数分布
# from scipy.stats import norm
# import numpy as np
# import matplotlib.pyplot as plt
import scipy.stats
#
#
#dmean=0.1297468
#dstd=0.177741305
dmean=0
dstd=1

# x=np.arange(-231,215,0.01)
#
# y=norm.pdf(x,dmean,dstd)
# plt.plot(x,y)
# plt.xlabel('x')
# plt.ylabel('y')
# plt.show()
# print(norm.pdf(10.86894904,dmean,dstd))
import scipy.stats
q=scipy.stats.norm(dmean, dstd).cdf(dmean+dstd)-scipy.stats.norm(dmean, dstd).cdf(dmean-dstd)
print(q)

#已知点位求面积
r=scipy.stats.norm.cdf(dstd,dmean,dstd)
rr=scipy.stats.norm.cdf(-dstd,dmean,dstd)
print(r-rr)(正一个std到-std之间的概率分布总和)

#已知面积求点位
y=scipy.stats.norm.ppf(0.9,dmean,dstd)
print(y) (左边到右边90%分布密度的对应点位)

  • Python排列与组合
import itertools

#组合(可以出现重复值)
l=list(itertools.combinations_with_replacement([1,2,3],2))
print(l)

#组合(不可以出现重复值)
l=list(itertools.combinations([1,2,3],2))
print(l)


#排列
ll=list(itertools.permutations([1,2,3],3))
print(ll)

  • Python并发之多进程的方法实例代码

这篇文章主要介绍了Python并发之多进程的方法实例代码,文中也提到了进程与线程的共同点,需要的朋友跟随脚本之家小编一起看看吧
一,进程的理论基础
一个应用程序,归根结底是一堆代码,是静态的,而进程才是执行中的程序,在一个程序运行的时候会有多个进程并发执行。
进程和线程的区别:
进程是系统资源分配的基本单位。
一个进程内可以包含多个线程,属于一对多的关系,进程内的资源,被其内的线程共享
线程是进程运行的最小单位,如果说进程是完成一个功能,那么其线程就是完成这个功能的基本单位
进程间资源不共享,多进程切换资源开销,难度大,同一进程内的线程资源共享,多线程切换资源开销,难度小
进程与线程的共同点:
都是为了提高程序运行效率,都有执行的优先权
二,Python的多进程( multiprocessing模块)
创建一个进程(和创建线程类似)
方法一:创建Process对象,通过对象调用start()方法启动进程

from multiprocessing import Process
def foo(name):
 print('hello,%s'%name)
if __name__ == '__main__':
 p1=Process(target=foo,args=('world',))
 p2 = Process(target=foo, args=('China',))
 p1.start()
 p2.start()
 print('=====主进程=====')
 # == == =主进程 == == =
 # hello, world
 # hello, China
 #主进程和子进程并发执行

注意:Process对象只能在在 if name == ‘main’:下创建,不然会报错。
方法二:自定义一个类继承Process类,并重写run()方法,将执行代码放在其内

from multiprocessing import Process
class MyProcess(Process):
 def __init__(self,name):
  super().__init__()
  self.name = name
 def run(self):
  print('hello,%s'%self.name)
if __name__ == '__main__':
 myprocess1 = MyProcess('world')
 myprocess2 = MyProcess('world')
 myprocess1.start()
 myprocess2.start()

Process内置方法
实例方法:
p.start():启动进程,并调用该子进程中的p.run()
p.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法
p.terminate():强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,使用该方法需要特别小心这种情况。如果p还保存了一个锁那么也将不会被释放,进而导致死锁
p.is_alive():如果p仍然运行,返回True
p.join([timeout]):主线程等待p终止。timeout是可选的超时时间
Process属性
p.daemon:默认值为False,如果设为True,代表p为后台运行的守护进程,当p的父进程终止时,p也随之终止,并且设定为True后,p不能创建自己的新进程,必须在p.start()之前设置
p.name:进程的名称
p.pid:进程的pid
p.exitcode:进程在运行时为None、如果为–N,表示被信号N结束(了解即可)
守护进程
类似于守护线程,只不过守护线程是对象的一个方法,而守护进程封装成对象的属性。

from multiprocessing import Process
import time
class MyProcess(Process):
 def __init__(self,name):
  super().__init__()
  self.name = name
 def run(self):
  time.sleep(3)
  print('hello,%s'%self.name)
if __name__ == '__main__':
 myprocess1=MyProcess('world')
 myprocess1.daemon = True
 myprocess1.start()
 print('结束')
#不会输出‘hello world',因为设置为守护进程,主进程不会等待也可以使用join方法,使主进程等待
from multiprocessing import Process
import time
class MyProcess(Process):
 def __init__(self,name):
  super().__init__()
  self.name = name
 def run(self):
  time.sleep(3)
  print('hello,%s'%self.name)
if __name__ == '__main__':
 myprocess1=MyProcess('world')
 myprocess1.daemon = True
 myprocess1.start()
 myprocess1.join() #程序阻塞
 print('结束')
join()

进程同步和锁
进程虽然不像线程共享资源,但是这并不意味着进程间不 需要加锁,比如不同进程会共享同一个终端 ( 屏幕),或者操作同一个文件,数据库,那么数据安全还是很有必要的,因此我们可以加锁,

from multiprocessing import Process,Lock
import time
def a_print(l): #需要传入对象,因为信息不共享
 l.acquire()
 print('我要打印信息')
 time.sleep(1)
 print('我打印完了')
 l.release()
if __name__ == '__main__':
 l = Lock()
 for i in range(20):
  p = Process(target=a_print,args=(l,))
  p.start()

信号量(Semaphore)
能够并发执行的进程数,超出的进程阻塞,直到有进程运行完成。
Semaphore管理一个内置的计数器,
每当调用acquire()时内置计数器-1;
调用release() 时内置计数器+1;
计数器不能小于0;当计数器为0时,acquire()将阻塞进程直到其他进程调用release()。

from multiprocessing import Process,Queue,Semaphore
import time,random
def seat(s,n):
 s.acquire()
 print('学生%d坐下了'%n)
 time.sleep(random.randint(1,2))
 s.release()
if __name__ == '__main__':
 s = Semaphore(5)
 for i in range(20):
  p = Process(target=seat,args=(s,i))
  p.start()
 print('-----主进程-------')

注意:其实信号量和锁类似,只是限制进程运行某个代码块的数量(锁为1个),并不是能限制并发的进程,如上述代码,一次性还是创建了20个进程
事件(Event)

from multiprocessing import Process,Event
import time, random
def eating(event):
 event.wait()
 print('去吃饭的路上...')
def makeing(event):
 print('做饭中')
 time.sleep(random.randint(1,2))
 print('做好了,快来...')
 event.set()
if __name__ == '__main__':
 event=Event()
 t1 = Process(target=eating,args=(event,))
 t2 = Process(target=makeing,args=(event,))
 t1.start()
 t2.start()
 # 做饭中
 # 做好了,快来...
 # 去吃饭的路上...

和线程事件几乎一致
进程队列(Queue)
进程队列是进程通讯的方式之一。使用multiprocessing 下的Queue

from multiprocessing import Process,Queue
import time
def func1(queue):
 while True:
  info=queue.get()
  if info == None:
   return
  print(info)
def func2(queue):
 for i in range(10):
  time.sleep(1)
  queue.put('is %d'%i)
 queue.put(None) #结束的标志
if __name__ == '__main__':
 q = Queue()
 p1 = Process(target=func1,args=(q,))
 p2 = Process(target=func2, args=(q,))
 p1.start()
 p2.start()
Queue类的方法,源码如下:
class Queue(object):
 def __init__(self, maxsize=-1): #可以传参设置队列最大容量
  self._maxsize = maxsize
 def qsize(self): #返回当前时刻队列中的个数
  return 0
 def empty(self): #是否为空
  return False
 def full(self): 是否满了
  return False
 def put(self, obj, block=True, timeout=None): #放值,blocked和timeout。如果blocked为True(默认值),并且timeout为正值,该方法会阻塞timeout指定的时间,直到该队列有剩余的空间。如果超时,会抛出Queue.Full异常。如果blocked为False,但该Queue已满,会立即抛出Queue.Full异常
  pass
 def put_nowait(self, obj): #=put(False)
  pass
 def get(self, block=True, timeout=None): 获取值,get方法有两个可选参数:blocked和timeout。如果blocked为True(默认值),并且timeout为正值,那么在等待时间内没有取到任何元素,会抛出Queue.Empty异常。如果blocked为False,有两种情况存在,如果Queue有一个值可用,则立即返回该值,否则,如果队列为空,则立即抛出Queue.Empty异常.
  pass
 def get_nowait(self): # = get(False)
  pass
 def close(self): #将队列关闭
  pass
 def join_thread(self): #略,几乎不用
  pass
 def cancel_join_thread(self):
  pass

进程队列源码注释进程池进程的消耗是很大的,因此我们不能无节制的开启新进程,因此我们可以 通过维护一个进程池来控制进程的数量 。这就不同于信号量,进程池可以从源头控制进程数量。在Python中可以通过如下方法使用同步调用

from multiprocessing import Pool
import time, random, os
def func(n):
 pid = os.getpid()
 print('进程%s正在处理第%d个任务'%(pid,n),'时间%s'%time.strftime('%H-%M-%S'))
 time.sleep(2)
 res = '处理%s'%random.choice(['成功','失败'])
 return res
if __name__ == '__main__':
 p = Pool(4) #创建4个进程,
 li = []
 for i in range(10):
  res = p.apply(func,args=(i,)) 交给进程池处理,处理完成才返回值,会阻塞,即使池内还有空余进程,相当于顺序执行
  li.append(res)
 for i in li:
  print(i)
#进程1916正在处理第0个任务 时间21-02-53
#进程1240正在处理第1个任务 时间21-02-55
#进程3484正在处理第2个任务 时间21-02-57
#进程7512正在处理第3个任务 时间21-02-59
#进程1916正在处理第4个任务 时间21-03-01
#进程1240正在处理第5个任务 时间21-03-03
#进程3484正在处理第6个任务 时间21-03-05
#进程7512正在处理第7个任务 时间21-03-07
#进程1916正在处理第8个任务 时间21-03-09
#进程1240正在处理第9个任务 时间21-03-11

从结果可以发现两点:
1.不是并发处理
2.一直都只有四个进程,串行执行
因此进程池提供了 异步处理 的方式

from multiprocessing import Pool
import time, random, os
def func(n):
 pid = os.getpid()
 print('进程%s正在处理第%d个任务'%(pid,n),'时间%s'%time.strftime('%H-%M-%S'))
 time.sleep(2)
 res = '处理%s'%random.choice(['成功','失败'])
 return res
 
if __name__ == '__main__':
 p = Pool(4)
 li = []
 for i in range(10):
  res = p.apply_async(func,args=(i,))

结果不会立刻返回,遇到阻塞,开启下一个进程,在这,相当于几乎同时出现四个打印结果(一个线程处理一个任务,处理完下个任务才能进来)
li.append(res)

p.close() #join之前需要关闭进程池
p.join() #因为异步,所以需要等待池内进程工作结束再继续
for i in li:
print(i.get()) #i是一个对象,通过get方法获取返回值,而同步则没有该方法

关于回调函数

from multiprocessing import Pool
import time, random, os
def func(n):
 pid = os.getpid()
 print('进程%s正在处理第%d个任务'%(pid,n),'时间%s'%time.strftime('%H-%M-%S'))
 time.sleep(2)
 res = '处理%s'%random.choice(['成功','失败'])
 return res
 
def foo(info):
 print(info) #传入值为进程执行结果
 
if __name__ == '__main__':
 p = Pool(4)
 li = []
 for i in range(10):
  res = p.apply_async(func,args=(i,),callback = foo) callback()回调函数会在进程执行完之后调用(主进程调用) 
  li.append(res)
 
 p.close() 
 p.join() 
 for i in li:
  print(i.get())

有回调函数
总结
以上所述是小编给大家介绍的Python并发之多进程的方法实例代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!


  • python 实现求和、计数、最大最小值、平均值、中位数、标准偏差、百分比
import sys
  
class Stats:
  
    def __init__(self, sequence):
        # sequence of numbers we will process
        # convert all items to floats for numerical processing
        self.sequence = [float(item) for item in sequence]
  
    def sum(self):
        if len(self.sequence) < 1:
            return None
        else:
            return sum(self.sequence)
  
    def count(self):
        return len(self.sequence)
  
    def min(self):
        if len(self.sequence) < 1:
            return None
        else:
            return min(self.sequence)
  
    def max(self):
        if len(self.sequence) < 1:
            return None
        else:
            return max(self.sequence)
  
    def avg(self):
        if len(self.sequence) < 1:
            return None
        else:
            return sum(self.sequence) / len(self.sequence)   
  
    def median(self):
        if len(self.sequence) < 1:
            return None
        else:
            self.sequence.sort()
            return self.sequence[len(self.sequence) // 2]
  
    def stdev(self):
        if len(self.sequence) < 1:
            return None
        else:
            avg = self.avg()
            sdsq = sum([(i - avg) ** 2 for i in self.sequence])
            stdev = (sdsq / (len(self.sequence) - 1)) ** .5
            return stdev
  
    def percentile(self, percentile):
        if len(self.sequence) < 1:
            value = None
        elif (percentile >= 100):
            sys.stderr.write('ERROR: percentile must be < 100.  you supplied: %s\n'% percentile)
            value = None
        else:
            element_idx = int(len(self.sequence) * (percentile / 100.0))
            self.sequence.sort()
            value = self.sequence[element_idx]
        return value

  • Python3 多线程
    多线程类似于同时执行多个不同程序,多线程运行有如下优点:
    使用线程可以把占据长时间的程序中的任务放到后台去处理。
    用户界面可以更加吸引人,比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度。
    程序的运行速度可能加快。
    在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较有用了。在这种情况下我们可以释放一些珍贵的资源如内存占用等等。
    每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
    每个线程都有他自己的一组CPU寄存器,称为线程的上下文,该上下文反映了线程上次运行该线程的CPU寄存器的状态。
    指令指针和堆栈指针寄存器是线程上下文中两个最重要的寄存器,线程总是在进程得到上下文中运行的,这些地址都用于标志拥有线程的进程地址空间中的内存。
    线程可以被抢占(中断)。
    在其他线程正在运行时,线程可以暂时搁置(也称为睡眠) – 这就是线程的退让。
    线程可以分为:
    内核线程:由操作系统内核创建和撤销。
    用户线程:不需要内核支持而在用户程序中实现的线程。
    Python3 线程中常用的两个模块为:
    _thread
    threading(推荐使用)
    thread 模块已被废弃。用户可以使用 threading 模块代替。所以,在 Python3 中不能再使用"thread" 模块。为了兼容性,Python3 将 thread 重命名为 “_thread”。

开始学习Python线程
Python中使用线程有两种方式:函数或者用类来包装线程对象。
函数式:调用 _thread 模块中的start_new_thread()函数来产生新线程。语法如下:
_thread.start_new_thread ( function, args[, kwargs] )
参数说明:
function - 线程函数。
args - 传递给线程函数的参数,他必须是个tuple类型。
kwargs - 可选参数。
实例

#!/usr/bin/python3

import _thread
import time

# 为线程定义一个函数
def print_time( threadName, delay):
   count = 0
   while count < 5:
      time.sleep(delay)
      count += 1
      print ("%s: %s" % ( threadName, time.ctime(time.time()) ))

# 创建两个线程
try:
   _thread.start_new_thread( print_time, ("Thread-1", 2, ) )
   _thread.start_new_thread( print_time, ("Thread-2", 4, ) )
except:
   print ("Error: 无法启动线程")

while 1:
   pass

执行以上程序输出结果如下:
Thread-1: Wed Apr 6 11:36:31 2016Thread-1: Wed Apr 6 11:36:33 2016Thread-2: Wed Apr 6 11:36:33 2016Thread-1: Wed Apr 6 11:36:35 2016Thread-1: Wed Apr 6 11:36:37 2016Thread-2: Wed Apr 6 11:36:37 2016Thread-1: Wed Apr 6 11:36:39 2016Thread-2: Wed Apr 6 11:36:41 2016Thread-2: Wed Apr 6 11:36:45 2016Thread-2: Wed Apr 6 11:36:49 2016
执行以上程后可以按下 ctrl-c to 退出。

线程模块
Python3 通过两个标准库 _thread 和 threading 提供对线程的支持。
_thread 提供了低级别的、原始的线程以及一个简单的锁,它相比于 threading 模块的功能还是比较有限的。
threading 模块除了包含 _thread 模块中的所有方法外,还提供的其他方法:
threading.currentThread(): 返回当前的线程变量。
threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
除了使用方法外,线程模块同样提供了Thread类来处理线程,Thread类提供了以下方法:
run(): 用以表示线程活动的方法。
start():启动线程活动。

join([time]): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。
isAlive(): 返回线程是否活动的。
getName(): 返回线程名。
setName(): 设置线程名。

使用 threading 模块创建线程
我们可以通过直接从 threading.Thread 继承创建一个新的子类,并实例化后调用 start() 方法启动新线程,即它调用了线程的 run() 方法:
实例

#!/usr/bin/python3

import threading
import time

exitFlag = 0

class myThread (threading.Thread):
    def __init__(self, threadID, name, counter):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.counter = counter
    def run(self):
        print ("开始线程:" + self.name)
        print_time(self.name, self.counter, 5)
        print ("退出线程:" + self.name)

def print_time(threadName, delay, counter):
    while counter:
        if exitFlag:
            threadName.exit()
        time.sleep(delay)
        print ("%s: %s" % (threadName, time.ctime(time.time())))
        counter -= 1

# 创建新线程
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)

# 开启新线程
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print ("退出主线程")

以上程序执行结果如下;
开始线程:Thread-1开始线程:Thread-2Thread-1: Wed Apr 6 11:46:46 2016Thread-1: Wed Apr 6 11:46:47 2016Thread-2: Wed Apr 6 11:46:47 2016Thread-1: Wed Apr 6 11:46:48 2016Thread-1: Wed Apr 6 11:46:49 2016Thread-2: Wed Apr 6 11:46:49 2016Thread-1: Wed Apr 6 11:46:50 2016退出线程:Thread-1Thread-2: Wed Apr 6 11:46:51 2016Thread-2: Wed Apr 6 11:46:53 2016Thread-2: Wed Apr 6 11:46:55 2016退出线程:Thread-2退出主线程

线程同步
如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步。
使用 Thread 对象的 Lock 和 Rlock 可以实现简单的线程同步,这两个对象都有 acquire 方法和 release 方法,对于那些需要每次只允许一个线程操作的数据,可以将其操作放到 acquire 和 release 方法之间。如下:
多线程的优势在于可以同时运行多个任务(至少感觉起来是这样)。但是当线程需要共享数据时,可能存在数据不同步的问题。
考虑这样一种情况:一个列表里所有元素都是0,线程"set"从后向前把所有元素改成1,而线程"print"负责从前往后读取列表并打印。
那么,可能线程"set"开始改的时候,线程"print"便来打印列表了,输出就成了一半0一半1,这就是数据的不同步。为了避免这种情况,引入了锁的概念。
锁有两种状态——锁定和未锁定。每当一个线程比如"set"要访问共享数据时,必须先获得锁定;如果已经有别的线程比如"print"获得锁定了,那么就让线程"set"暂停,也就是同步阻塞;等到线程"print"访问完毕,释放锁以后,再让线程"set"继续。
经过这样的处理,打印列表时要么全部输出0,要么全部输出1,不会再出现一半0一半1的尴尬场面。
实例

#!/usr/bin/python3

import threading
import time

class myThread (threading.Thread):
    def __init__(self, threadID, name, counter):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.counter = counter
    def run(self):
        print ("开启线程: " + self.name)
        # 获取锁,用于线程同步
        threadLock.acquire()
        print_time(self.name, self.counter, 3)
        # 释放锁,开启下一个线程
        threadLock.release()

def print_time(threadName, delay, counter):
    while counter:
        time.sleep(delay)
        print ("%s: %s" % (threadName, time.ctime(time.time())))
        counter -= 1

threadLock = threading.Lock()
threads = []

# 创建新线程
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)

# 开启新线程
thread1.start()
thread2.start()

# 添加线程到线程列表
threads.append(thread1)
threads.append(thread2)

# 等待所有线程完成
for t in threads:
    t.join()
print ("退出主线程")

执行以上程序,输出结果为:
开启线程: Thread-1开启线程: Thread-2Thread-1: Wed Apr 6 11:52:57 2016Thread-1: Wed Apr 6 11:52:58 2016Thread-1: Wed Apr 6 11:52:59 2016Thread-2: Wed Apr 6 11:53:01 2016Thread-2: Wed Apr 6 11:53:03 2016Thread-2: Wed Apr 6 11:53:05 2016退出主线程

线程优先级队列( Queue)
Python 的 Queue 模块中提供了同步的、线程安全的队列类,包括FIFO(先入先出)队列Queue,LIFO(后入先出)队列LifoQueue,和优先级队列 PriorityQueue。
这些队列都实现了锁原语,能够在多线程中直接使用,可以使用队列来实现线程间的同步。
Queue 模块中的常用方法:
Queue.qsize() 返回队列的大小
Queue.empty() 如果队列为空,返回True,反之False
Queue.full() 如果队列满了,返回True,反之False
Queue.full 与 maxsize 大小对应
Queue.get([block[, timeout]])获取队列,timeout等待时间
Queue.get_nowait() 相当Queue.get(False)
Queue.put(item) 写入队列,timeout等待时间
Queue.put_nowait(item) 相当Queue.put(item, False)
Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号
Queue.join() 实际上意味着等到队列为空,再执行别的操作
实例

#!/usr/bin/python3

import queue
import threading
import time

exitFlag = 0

class myThread (threading.Thread):
    def __init__(self, threadID, name, q):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.q = q
    def run(self):
        print ("开启线程:" + self.name)
        process_data(self.name, self.q)
        print ("退出线程:" + self.name)

def process_data(threadName, q):
    while not exitFlag:
        queueLock.acquire()
        if not workQueue.empty():
            data = q.get()
            queueLock.release()
            print ("%s processing %s" % (threadName, data))
        else:
            queueLock.release()
        time.sleep(1)

threadList = ["Thread-1", "Thread-2", "Thread-3"]
nameList = ["One", "Two", "Three", "Four", "Five"]
queueLock = threading.Lock()
workQueue = queue.Queue(10)
threads = []
threadID = 1

# 创建新线程
for tName in threadList:
    thread = myThread(threadID, tName, workQueue)
    thread.start()
    threads.append(thread)
    threadID += 1

# 填充队列
queueLock.acquire()
for word in nameList:
    workQueue.put(word)
queueLock.release()

# 等待队列清空
while not workQueue.empty():
    pass

# 通知线程是时候退出
exitFlag = 1

# 等待所有线程完成
for t in threads:
    t.join()
print ("退出主线程")

以上程序执行结果:
开启线程:Thread-1开启线程:Thread-2开启线程:Thread-3Thread-3 processing OneThread-1 processing TwoThread-2 processing ThreeThread-3 processing FourThread-1 processing Five退出线程:Thread-3退出线程:Thread-2退出线程:Thread-1退出主线程

在线程里,传递参数有三种方法:

1、使用元组传递 threading.Thread(target=方法名,args=(参数1,参数2, …))

import timeimport threading
def song(a,b,c):
    print(a, b, c)
    for i in range(5):
        print("song")
        time.sleep(1)if __name__ == "__main__":
    threading.Thread(target=song,args=(1,2,3)).start()

2、使用字典传递 threading.Thread(target=方法名, kwargs={“参数名”: 参数1, “参数名”: 参数2, …})

threading.Thread(target=song,kwargs={"a":1,"c":3,"b":2}).start() #参数顺序可以变

3、混合使用元组和字典 threading.Thread(target=方法名,args=(参数1, 参数2, …), kwargs={“参数名”: 参数1,“参数名”: 参数2, …})

threading.Thread(target=song,args=(1,),kwargs={"c":3,"b":2}).start()

上面那个理解不了,我这个应该更容易懂:

import timeimport threading# 使用 threading 模块创建线程import queue#优先级队列模块#线程优先级队列(Queue)
exitFlag = 0class myThread (threading.Thread):
    def __init__(self, threadID, name, q):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.q = q
    def run(self):
        print ("开启线程:" + self.name)
        process_data(self.threadID,self.name, self.q)
        print ("退出线程:" + self.name)def process_data(id,threadName, q):
    while not exitFlag:
        id += 1
        if id >= 4:
            data = q.get()
            print ("%s processing %s" % (threadName, data))
        time.sleep(1)
threadList = ["Thread-1", "Thread-2", "Thread-3"]
nameList = ["One", "Two", "Three", "Four", "Five"]
workQueue = queue.Queue(10)
threads = []
threadID = 1# 填充队列for word in nameList:
    workQueue.put(word)# 创建新线程for tName in threadList:
    thread = myThread(threadID, tName, workQueue)
    thread.start()
    threads.append(thread)
    threadID += 1# 等待队列清空while not workQueue.empty():
    pass# 通知线程是时候退出
exitFlag = 1# 等待所有线程完成for t in threads:
    t.join()print ("退出主线程")

  • 利用Python scipy.signal.filtfilt() 实现信号滤波

在使用Python进行信号处理过程中,利用 scipy.signal.filtfilt()可以快速帮助实现信号的滤波。

1.函数的介绍

(1).滤波函数

scipy.signal.filtfilt(b, a, x, axis=-1, padtype=‘odd’, padlen=None, method=‘pad’, irlen=None)

输入参数:

b: 滤波器的分子系数向量

a: 滤波器的分母系数向量

x: 要过滤的数据数组。(array型)

axis: 指定要过滤的数据数组x的轴

padtype: 必须是“奇数”、“偶数”、“常数”或“无”。这决定了用于过滤器应用的填充信号的扩展类型。{‘odd’, ‘even’, ‘constant’, None}

padlen:在应用滤波器之前在轴两端延伸X的元素数目。此值必须小于要滤波元素个数- 1。(int型或None)

method:确定处理信号边缘的方法。当method为“pad”时,填充信号;填充类型padtype和padlen决定,irlen被忽略。当method为“gust”时,使用古斯塔夫森方法,而忽略padtype和padlen。{“pad” ,“gust”}

irlen:当method为“gust”时,irlen指定滤波器的脉冲响应的长度。如果irlen是None,则脉冲响应的任何部分都被忽略。对于长信号,指定irlen可以显著改善滤波器的性能。(int型或None)

输出参数:

y:滤波后的数据数组

(2).滤波器构造函数(仅介绍Butterworth滤波器)

scipy.signal.butter(N, Wn, btype=‘low’, analog=False, output=‘ba’)

输入参数:

N:滤波器的阶数

Wn:归一化截止频率。计算公式Wn=2*截止频率/采样频率。(注意:根据采样定理,采样频率要大于两倍的信号本身最大的频率,才能还原信号。截止频率一定小于信号本身最大的频率,所以Wn一定在0和1之间)。当构造带通滤波器或者带阻滤波器时,Wn为长度为2的列表。

btype : 滤波器类型{‘lowpass’, ‘highpass’, ‘bandpass’, ‘bandstop’},

output : 输出类型{‘ba’, ‘zpk’, ‘sos’},

输出参数:

b,a: IIR滤波器的分子(b)和分母(a)多项式系数向量。output=‘ba’

z,p,k: IIR滤波器传递函数的零点、极点和系统增益. output= ‘zpk’

sos: IIR滤波器的二阶截面表示。output= ‘sos’

2.函数的使用

信号滤波中最常用的无非低通滤波、高通滤波和带通滤波。下面简单介绍这三种滤波的使用过程:

(1).高通滤波

#这里假设采样频率为1000hz,信号本身最大的频率为500hz,要滤除10hz以下频率成分,即截至频率为10hz,则wn=2*10/1000=0.02

from scipy import signal

b, a = signal.butter(8, 0.02, ‘highpass’)
filtedData = signal.filtfilt(b, a, data)#data为要过滤的信号

(2).低通滤波

#这里假设采样频率为1000hz,信号本身最大的频率为500hz,要滤除10hz以上频率成分,即截至频率为10hz,则wn=2*10/1000=0.02

from scipy import signal

b, a = signal.butter(8, 0.02, ‘lowpass’)
filtedData = signal.filtfilt(b, a, data) #data为要过滤的信号

(3).带通滤波

#这里假设采样频率为1000hz,信号本身最大的频率为500hz,要滤除10hz以下和400hz以上频率成分,即截至频率为10hz和400hz,则wn1=210/1000=0.02,wn2=2400/1000=0.8。Wn=[0.02,0.8]

from scipy import signal

b, a = signal.butter(8, [0.02,0.8], 'bandpass')
filtedData = signal.filtfilt(b, a, data)   #data为要过滤的信号

参考:

1.https://docs.scipy.org/doc/scipy-0.18.1/reference/generated/scipy.signal.filtfilt.html

2.https://docs.scipy.org/doc/scipy-0.18.1/reference/generated/scipy.signal.butter.html#scipy.signal.butter


  • excel转数据库、excel转sqlite3
  • csv转数据库、csv转sqlite3
import pandas
import csv, sqlite3
conn= sqlite3.connect("dbname.db")
df = pandas.read_csv('TWAP.csv',encoding='gbk')
df.to_sql('tablename', conn, if_exists='append', index=False)
print('ok')



db = sqlite3.connect('dbname.db')
cur = db.cursor()
cur.execute("select * from tablename")
col_name_list = [tuple[0] for tuple in cur.description]
print (col_name_list)

  • pyhton 字符串转时间戳
import time 
str='2017-11-23 16:10:10' 
t=time.mktime(time.strptime(str, "%Y-%m-%d %H:%M:%S")) 
print(t)

  • 轻松理解 Python 中的 async await 概念

注: 所有的讲解都在代码的注释里.

from time import sleep, time


def demo1():
    """
    假设我们有三台洗衣机, 现在有三批衣服需要分别放到这三台洗衣机里面洗.
    """
    
    def washing1():
        sleep(3)  # 第一台洗衣机, 需要洗3秒才能洗完 (只是打个比方)
        print('washer1 finished')  # 洗完的时候, 洗衣机会响一下, 告诉我们洗完了
    
    def washing2():
        sleep(2)
        print('washer2 finished')
    
    def washing3():
        sleep(5)
        print('washer3 finished')
    
    washing1()
    washing2()
    washing3()
    
    """
    这个还是很容易理解的, 运行 demo1(), 那么需要10秒钟才能把全部衣服洗完.
    没错, 大部分时间都花在挨个地等洗衣机上了.
    """


def demo2():
    """
    现在我们想要避免无谓的等待, 为了提高效率, 我们将使用 async.
    washing1/2/3() 本是 "普通函数", 现在我们用 async 把它们升级为 "异步函数".
    
    注: 一个异步的函数, 有个更标准的称呼, 我们叫它 "协程" (coroutine).
    """
    
    async def washing1():
        sleep(3)
        print('washer1 finished')
    
    async def washing2():
        sleep(2)
        print('washer2 finished')
    
    async def washing3():
        sleep(5)
        print('washer3 finished')
    
    washing1()
    washing2()
    washing3()
    
    """
    从正常人的理解来看, 我们现在有了异步函数, 但是却忘了定义应该什么时候 "离开" 一台洗衣
    机, 去看看另一个... 这就会导致, 现在的情况是我们一边看着第一台洗衣机, 一边着急地想着
    "是不是该去开第二台洗衣机了呢?" 但又不敢去 (只是打个比方), 最终还是花了10秒的时间才
    把衣服洗完.
    
    PS: 其实 demo2() 是无法运行的, Python 会直接警告你:
        RuntimeWarning: coroutine 'demo2.<locals>.washing1' was never awaited
        RuntimeWarning: coroutine 'demo2.<locals>.washing2' was never awaited
        RuntimeWarning: coroutine 'demo2.<locals>.washing3' was never awaited
    """


def demo3():
    """
    现在我们吸取了上次的教训, 告诉自己洗衣服的过程是 "可等待的" (awaitable), 在它开始洗衣服
    的时候, 我们可以去弄别的机器.
    """
    
    async def washing1():
        await sleep(3)  # 注意这里加入了 await
        print('washer1 finished')
    
    async def washing2():
        await sleep(2)
        print('washer2 finished')
    
    async def washing3():
        await sleep(5)
        print('washer3 finished')
    
    washing1()
    washing2()
    washing3()
    
    """
    尝试运行一下, 我们会发现还是会报错 (报错内容和 demo2 一样). 这里我说一下原因, 以及在
    demo4 中会给出一个最终答案:
        1. 第一个问题是, await 后面必须跟一个 awaitable 类型或者具有 __await__ 属性的
        对象. 这个 awaitable, 并不是我们认为 sleep() 是 awaitable 就可以 await 了,
        常见的 awaitable 对象应该是:
            await asyncio.sleep(3)  # asyncio 库的 sleep() 机制与 time.sleep() 不
            # 同, 前者是 "假性睡眠", 后者是会导致线程阻塞的 "真性睡眠"
            await an_async_function()  # 一个异步的函数, 也是可等待的对象
        以下是不可等待的:
            await time.sleep(3)
            x = await 'hello'  # <class 'str'> doesn't define '__await__'
            x = await 3 + 2  # <class 'int'> dosen't define '__await__'
            x = await None  # ...
            x = await a_sync_function()  # 普通的函数, 是不可等待的
            
        2. 第二个问题是, 如果我们要执行异步函数, 不能用这样的调用方法:
            washing1()
            washing2()
            washing3()
        而应该用 asyncio 库中的事件循环机制来启动 (具体见 demo4 讲解).
    """


def demo4():
    """
    这是最终我们想要的实现.
    """
    import asyncio  # 引入 asyncio 库
    
    async def washing1():
        await asyncio.sleep(3)  # 使用 asyncio.sleep(), 它返回的是一个可等待的对象
        print('washer1 finished')
    
    async def washing2():
        await asyncio.sleep(2)
        print('washer2 finished')
    
    async def washing3():
        await asyncio.sleep(5)
        print('washer3 finished')
    
    """
    事件循环机制分为以下几步骤:
        1. 创建一个事件循环
        2. 将异步函数加入事件队列
        3. 执行事件队列, 直到最晚的一个事件被处理完毕后结束
        4. 最后建议用 close() 方法关闭事件循环, 以彻底清理 loop 对象防止误用
    """
    # 1. 创建一个事件循环
    loop = asyncio.get_event_loop()
    
    # 2. 将异步函数加入事件队列
    tasks = [
        washing1(),
        washing2(),
        washing3(),
    ]
    
    # 3. 执行事件队列, 直到最晚的一个事件被处理完毕后结束
    loop.run_until_complete(asyncio.wait(tasks))
    """
    PS: 如果不满意想要 "多洗几遍", 可以多写几句:
        loop.run_until_complete(asyncio.wait(tasks))
        loop.run_until_complete(asyncio.wait(tasks))
        loop.run_until_complete(asyncio.wait(tasks))
        ...
    """
    
    # 4. 如果不再使用 loop, 建议养成良好关闭的习惯
    # (有点类似于文件读写结束时的 close() 操作)
    loop.close()
    
    """
    最终的打印效果:
        washer2 finished
        washer1 finished
        washer3 finished
        elapsed time = 5.126561641693115
        	(毕竟切换线程也要有点耗时的)
        
    说句题外话, 我看有的博主的加入事件队列是这样写的:
        tasks = [
            loop.create_task(washing1()),
            loop.create_task(washing2()),
            loop.create_task(washing3()),
        ]
        运行的效果是一样的, 暂不清楚为什么他们这样做.
    """


if __name__ == '__main__':
    # 为验证是否真的缩短了时间, 我们计个时
    start = time()
    
    # demo1()  # 需花费10秒
    # demo2()  # 会报错: RuntimeWarning: coroutine ... was never awaited
    # demo3()  # 会报错: RuntimeWarning: coroutine ... was never awaited
    demo4()  # 需花费5秒多一点点
    
    end = time()
    print('elapsed time = ' + str(end - start))

  • 多线程实例
#coding=utf-8
import threading
import time


def music(value):
    print(value+1)
    time.sleep(1)
    print("FC")


def move(value):
    print(value+2)
    time.sleep(5)
    print("FE")





while True:
    time.sleep(1)

    t1 = threading.Thread(target=music, args=(1,))

    t2 = threading.Thread(target=move, args=(2,))

    t1.start()
    t2.start()

    print("f")

  • Python GARCH模型
import numpy as np
import pyflux as pf
import pandas as pdfrom pandas.io.data 
import DataReaderfrom datetime 
import datetime
jpm = DataReader('JPM', 'yahoo', datetime(2006,1,1), datetime(2016,3,10))
returns = pd.DataFrame(np.diff(np.log(jpm['Adj Close'].values)))
model = pf.GARCH(returns,p=1,q=1)
x = model.fit()

  • tkinter 弹窗 Tkinter
import tkinter as tk

root = tk.Tk()
root.title('Leo ')
root.geometry("800x800")
p = tk.PhotoImage(file='收款.png')
p2=tk.PhotoImage(file='乞讨.png')
w2=tk.Label(root,image=p2, text="\n客官服务是否还满意\n\n行行好赏口饭吃吧!\n",compound='bottom',font=12)
w = tk.Label(root,image=p)
w2.pack()
w.pack()


root.mainloop()

  • 解决python3 UnicodeEncodeError: ‘gbk’ codec can’t encode character ‘\xXX’ in position XX
    从网上抓了一些字节流,想打印出来结果发生了一下错误:
    UnicodeEncodeError: ‘gbk’ codec can’t encode character ‘\xbb’ in position 8530: illegal multibyte sequence
    代码
import urllib.request
res=urllib.request.urlopen('http://www.baidu.com')
htmlBytes=res.read()print(htmlBytes.decode('utf-8'))

错误信息让人很困惑,为什么用的是’utf-8’解码,错误信息却提示’gbk’错误呢?

不仅如此,从百度首页的html中发现以下代码:

这说明网页的确用的是utf-8,为什么会出现Error呢?

在python3里,有几点关于编码的常识
1.字符就是unicode字符,字符串就是unicode字符数组
如果用以下代码测试,
print(‘a’==‘\u0061’)
会发现结果为True,足以说明两者的等价关系。

2.str转bytes叫encode,bytes转str叫decode,如上面的代码就是将抓到的字节流给decode成unicode数组
我根据上面的错误信息分析了字节流中出现\xbb的地方,发现有个\xc2\xbb的特殊字符»,我怀疑是它无法被解码。
用以下代码测试后
print(b’\xc2\xbb’.decode(‘utf-8’))
它果然报错了:UnicodeEncodeError: ‘gbk’ codec can’t encode character ‘\xbb’ in position 0: illegal multibyte sequence

上网找了下utf-8编码表,发现的确特殊字符»的utf-8形式就是c2bb,unicode是’\u00bb’,为什么无法解码呢。。。
仔细看看错误信息,它提示’gbk’无法encode,但是我的代码是utf-8无法decode,压根牛头不对马嘴,终于让我怀疑是print函数出错了。。于是立即有了以下的测试
print(‘\u00bb’)
结果报错了:UnicodeEncodeError: ‘gbk’ codec can’t encode character ‘\xbb’ in position 0: illegal multibyte sequence

原来是print()函数自身有限制,不能完全打印所有的unicode字符。
知道原因后,google了一下解决方法,其实print()函数的局限就是Python默认编码的局限,因为系统是win7的,python的默认编码不是’utf-8’,改一下python的默认编码成’utf-8’就行了

import ioimport sysimport urllib.request
sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf8') #改变标准输出的默认编码
res=urllib.request.urlopen('http://www.baidu.com')
htmlBytes=res.read()print(htmlBytes.decode('utf-8'))

运行后不报错了,但是居然有好多乱码(英文显示正常,中文则显示乱码)!!又一阵折腾后发现是控制台的问题,具体来说就是我在cmd下运行该脚本会有乱码,而在IDLE下运行却很正常。
由此我推测是cmd不能很好地兼容utf8,而IDLE就可以,甚至在IDLE下运行,连“改变标准输出的默认编码”都不用,因为它默认就是utf8。如果一定要在cmd下运行,那就改一下编码,比如我换成“gb18030”,就能正常显示了:

sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='gb18030')
    #改变标准输出的默认编码

最后,附上一些常用的和中文有关的编码的名称,分别赋值给encoding,就可以看到不同的效果了:

编码名称 用途
utf8 所有语言
gbk 简体中文
gb2312 简体中文
gb18030 简体中文
big5 繁体中文
big5hkscs 繁体中文


  • Python redis
    Redis Flushall 命令用于清空整个 Redis 服务器的数据(删除所有数据库的所有 key )。
    redis.flushall()
#!/usr/bin/python
# -*- coding:utf-8 -*-
# __author__ = 'Jack'

import time
import redis

pool = redis.ConnectionPool(host='127.0.0.1', port=6379,db=19, password='82325588')
r = redis.Redis(connection_pool=pool)
r.flushall()  # 清空Redis


'''
一、字符串 strings

Python操作Redis的redis模块对字符串(string)的主要操作函数包括:
SET、GET、GETSET、SETEX、SETNX、MSET、MSETNX、INCR(INCRBY,DECR,DECRBY在python中用同一个函数incr实现)、APPEND、SETRANGE、STRLEN。
函数说明如下:

1、SET:为指定的键(key)设置值(value), set(self, name, value, **kwargs)。
2、GET:获取指定键(key)绑定的值(value),get(self, name)。
3、GETSET:为指定的键(key)设置新的值(value),并返回旧的值(old Value),getset(self, name, value)
4、SETEX:为指定的键(key)设置过期以秒(second)计的过期时间,setex(self, name, value, time)
5、SETNX:键(key)不存在时,为键(key)指定值(value),setnx(self, name, value)
6、MSET:一次性设置多个键-值(key-value)对,函数设置的键-值对(即mapping所指内容)数据要以Python字典数据类型传入,mset(self, mapping)
7、MSETNX:键-值(key-value)对不存在时,设置键-值(key-value)对,msetnx(self, mapping),mapping值参考6
8、INCR:自增函数,默认步长为1,通过对步长(amount)大小以及字符的控制实现了INCRBY(amount>=1)、DECR(amount=-1)、DECRBY(amount<=-1)等函数功能,incr(self, name, amount=1)
9、APPEND:为指定的字符串追加值,若不存在则直接创建,append(self, key, value)
10、SETRANGE:用 value 参数覆写给定 key 所储存的字符串值,从偏移量 offset 开始,setrange(self, name, offset, value)
11、STRLEN:返回字符串的长度,当name不存在时返回0,strlen(self, name)
'''

def test_redis_string():
    r.setex('string_0', value='liaogx', time=2)  # 设置新值,过期时间为3s
    r.mset(k1 = 'v1', k2 = 'v2', k3 = 'v3')  # 批量设置新值
    print(r.mget('k1', 'k2', 'k3', 'k4'))  # 批量获取新值
    print(r.getset('string_0', 'liaogaoxiang'))  # 设置新值并获取原来的值
    print(r.getrange('string_0', 0, 1))  # 获取子序列 0 <= x <= 1
    r.setrange('string_0', 0, 'LIAO')  # 修改字符串内容,从指定字符串索引开始向后替换(新值太长时,则向后添加),返回值的长度
    i = 0
    while i < 4:
        print(r.get('string_0'))
        time.sleep(1)
        i += 1
    source = 'foo'
    r.set('string_1', source)
    r.setbit('string_1', 7, 1)
    '''
    注:如果在Redis中有一个对应: string_1 = "foo",
        那么字符串foo的二进制表示为:01100110 01101111 01101111
        所以,如果执行 setbit('string_1', 7, 1),则就会将第7位设置为1,
        那么最终二进制则变成 01100111 01101111 01101111,即:"goo"
    '''
    print(r.get('string_1'))
    print(r.getbit('string_1', 7))  # 获取n1对应的值的二进制表示中的某位的值 (0或1)
    r.set('string_2', '廖高祥')
    print(r.strlen('string_2'))  # 返回对应的字节长度(一个汉字3个字节)
    r.set('string_3', 1)
    r.incr('string_3', amount=10)
    r.decr('string_3', amount=1)
    print(r.get('string_3'))  # 自增string_3对应的值,当name不存在时,则创建name=amount,否则,则自增。
    r.append('string_3', 111)
    print(r.get('string_3'))  # 在redis string_3对应的值后面追加内容
    




'''
二、列表 lists

Python操作Redis主要利用了redis模块来实现,list表操作函数主要模拟了Redis操作命令LPUSH,LRANGE,LINDEX,BLPOP,BRPOP。函数说明如下:

1、lpush函数实现了从向指定redis列表头部压入数据功能,lpush key value
2、lrange获取列表指定范围的函数,lrange key start end
3、lindex根据列表下标量获取列表元素值, lindex key index
4、blpop从列表头部取出第一个元素,返回该元素值并从列表删除(l代表left,左边)
5、brpop从列表尾部取出第一个元素,返回该元素值并从列表删除(l代表right,右边)
6、LPUSHX、RPUSHX以及其他一些Redis列表(List)函数目前版本无法实现,如有可实现方法博客代码事例将会得到更新。
'''
def test_redis_list():
    r.lpush('list_0', 11)  # 保存顺序为: 33,22,11
    r.lpushx('list_0', 00)  # 在name对应的list中添加元素,只有name已经存在时,值添加到列表的最左边
    print(r.llen('list_0'))  # name对应的list元素的个数
    
    r.linsert('list_0', 'before', 11, 99)  # 在11之前插入值99
    r.lset('list_0', 1, 88)  # 对name对应的list中的某一个索引位置重新赋值
    print(r.lrange('list_0', 0, -1))  # 在name对应的列表分片获取数据
    
    r.lrem('list_0', 88, num=1)  # 在name对应的list中删除指定的值.num=0,删除列表中所有的指定值;num=2,从前到后,删除2个;num=-2,从后向前,删除2个
    print(r.lrange('list_0', 0, -1))
    
    print(r.lpop('list_0'))  # 在name对应的列表的左侧获取第一个元素并在列表中移除,返回值则是第一个元素
    print(r.lindex('list_0', 0))  # 在name对应的列表中根据索引获取列表元素
    r.lpush('list_1', 11)  # index为0
    r.rpush('list_1', 22)
    r.rpush('list_1', 33)
    r.rpush('list_1', 44)
    r.rpush('list_1', 55)  # index为4
    r.ltrim('list_1', 1, 3)  # 在name对应的列表中移除没有在[start-end]索引之间的值
    print(r.lrange('list_1', 0, -1))
    
    r.rpoplpush('list_1', 'list_1')  # 从一个列表取出最右边的元素,同时将其添加至另一个列表的最左边;src要取数据的列表的name, dst要添加数据的列表的name
    print(r.lrange('list_1', 0, -1))
    
    r.brpoplpush('list_1', 'list_1', timeout=3)  # # timeout,当src对应的列表中没有数据时,阻塞等待其有数据的超时时间(秒),0 表示永远阻塞
    print(r.lrange('list_1', 0, -1))
    
    print(r.blpop('list_1', 3))  # 从列表头部取出第一个元素,返回该元素值并从列表删除(l代表left,左边)
    print(r.lrange('list_1', 0, -1))
    '''
        # 由于redis类库中没有提供对列表元素的增量迭代,如果想要循环name对应的列表的所有元素,那么就需要:
        # 1、获取name对应的所有列表
        # 2、循环列表
        # 但是,如果列表非常大,那么就有可能在第一步时就将程序的内容撑爆,所有有必要自定义一个增量迭代的功能:
    '''
    print('自定义增量迭代:')
    #r.flushall()
    r.lpush('list_1', 11)  # index为0
    r.rpush('list_1', 22)
    r.rpush('list_1', 33)
    r.rpush('list_1', 44)
    r.rpush('list_1', 55)  # index为4
    
    for item in list_iter('list_1'):
        print(item)

def list_iter(name):
    list_count = r.llen(name)
    for index in range(list_count):
        yield r.lindex(name, index)




'''
三、集合 sets

Redis 数据库集合对象(set object)是由string类型的无重复元素的无需集合,底层编码可以是intset或者hashtable。
intset编码的集合对象用整数集合最为底层实现,所有对象元素保存在整数集合中。
Python的redis模块实现了 SADD、SCARD 、SDIFF 、SDIFFSTORE、SINTER 、SINTERSTORE、SISMEMBER 、SMEMBERS 、SMOVE、SPOP、SRANDMEMBER、SREM、SUNION、SUNIONSTORE操作命令的基本用法。函数说明如下:

1、SADD:向集合对象添加成员,sadd(self, name, value)
2、SCARD:获取集合元素个数,scard(self, name)
3、SDIFF:返回给定多个集合对象的差集(set key1-set key2..-set keyn),从左到右计算集合差集,sdiff(self, keys, *args)
4、SDIFFSTORE:返回给定给定多个集合对象的差集并存储在目标(dest)集合中,sdiffstore(self, dest, keys, *args)
5、SINTER:返回给定所有集合(keys, args)的交集, sinter(self, keys, args)
6、SINTERSTORE:返回给定所有集合(keys, args)的交集并存储在 集合(dest) 中, sinterstore(self, dest, keys, args)
7、SISMEMBER:判断 value元素是否是集合 name 的成员,返回布尔逻辑值True或者False,sismember(self, name, value)
8、SMEMBERS:返回集合中所元素值的Python集合类型数据,smembers(self, name)
9、SMOVE:将元素value从集合src移动到 集合 dest。若元素value在集合src中不存在,则集合dest中不会添加元素value, smove(self, src, dest, value)
10、SPOP:移除并返回集合中的一个随机元素, spop(self, name)
11、SRANDMEMBER:返回集合中一个随机数,但是不做移除操作, srandmember(self, name)。从Redis 2.6 版本开始, 在命令行下Srandmember 命令接受可选返回元素数量的参数 redis>SRANDMEMBER name count
12、SREM:移除集合中一个元素,srem(self, name, value),redis模块任然沿用Redis 2.4 版本以前的只接受单个元素的用法。
13、SUNION:返回所有给定集合的并集中所有元素,sunion(self, keys, *args)
14、SUNIONSTORE:所有给定集合的并集存储在集合dest 中, sunionstore(self, dest, keys, *args)
15、SSCAN:迭代集合中的元素,sscan(self, name, cursor=0, match=None, count=None)
'''
def test_redis_set():
    r.sadd('set_1', 'v1', 'v1', 'v2', 'v3')  # name对应的集合中添加元素
    r.sadd('set_2', 'v2', 'v4')  # name对应的集合中添加元素
    print(r.scard('set_1'))  # 获取name对应的集合中元素个数
    print(r.sdiff('set_1', 'set_2'))  #在第一个name对应的集合中且不在其他name对应的集合的元素集合
    
    r.sdiffstore('set_3', 'set_1', 'set_2')  # 获取第一个name对应的集合中且不在其他name对应的集合,再将其新加入到dest对应的集合中
    print(r.smembers('set_3'))  # 获取set_3对应的集合的所有成员
    
    print(r.sinter('set_1', 'set_2'))  # 获取set_1, set_2对应集合的交集
    r.sinterstore('set_4', 'set_1', 'set_2')  # 获取set_1, set_2对应集合的交集,并将其存放到集合是set_4中
    print(r.smembers('set_4'))
    
    print(r.sunion('set_1', 'set_2'))  # 获取set_1, set_2对应集合的并集
    
    r.sunionstore('set_5', 'set_1', 'set_2')  # 获取set_1, set_2对应集合的交集,并将其存放到集合是set_5中
    print(r.smembers('set_5'))
    
    print(r.sismember('set_4', 'v4'))  # 检查value是否是name对应的集合的成员
    
    r.smove('set_2', 'set_1', 'v4')  # 将集合set_2中成员v4移至集合set_1中
    print(r.smembers('set_1'))
    r.srem('set_1', 'v1')  # 在name对应的集合中删除某些值
    
    print(r.spop('set_1'))  # 从集合的右侧(尾部)移除一个成员,并将其返回 注意:集合是无序的,故结果随机!
    
    print(r.srandmember('set_1'))  # 从name对应的集合中随机获取 numbers 个元素(Redis 2.6+)
    
    
    



'''
四、有序集合 sorted sets

| 命令 | 描述 | | ------------------------------------------------------------ | ------------------------------------------------------------ | 
| Redis Zadd 命令 | 向有序集合添加一个或多个成员,或者更新已存在成员的分数 | 
| Redis Zcard 命令 | 获取有序集合的成员数 | 
| Redis Zcount 命令 | 计算在有序集合中指定区间分数的成员数 | 
| Redis Zincrby 命令 | 有序集合中对指定成员的分数加上增量 increment | 
| Redis Zinterstore 命令 | 计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中 | 
| Redis Zlexcount 命令 | 在有序集合中计算指定字典区间内成员数量 | 
| Redis Zrange 命令 | 通过索引区间返回有序集合成指定区间内的成员 | 
| Redis Zrangebylex 命令 | 通过字典区间返回有序集合的成员 | 
| Redis Zrangebyscore 命令 | 通过分数返回有序集合指定区间内的成员 | 
| Redis Zrank 命令 | 返回有序集合中指定成员的索引 | 
| Redis Zrem 命令 | 移除有序集合中的一个或多个成员 | 
| Redis Zremrangebylex 命令 | 移除有序集合中给定的字典区间的所有成员 | 
| Redis Zremrangebyrank 命令 | 移除有序集合中给定的排名区间的所有成员 | 
| Redis Zremrangebyscore 命令 | 移除有序集合中给定的分数区间的所有成员 | 
| Redis Zrevrange 命令 | 返回有序集中指定区间内的成员,通过索引,分数从高到底 | 
| Redis Zrevrangebyscore 命令 | 返回有序集中指定分数区间内的成员,分数从高到低排序 | 
| Redis Zrevrank 命令 | 返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序 | 
| Redis Zscore 命令 | 返回有序集中,成员的分数值 | 
| Redis Zunionstore 命令 | 计算给定的一个或多个有序集的并集,并存储在新的 key 中 | 
| Redis Zscan 命令 | 迭代有序集合中的元素(包括元素成员和元素分值) |
'''
def test_redis_sorted_set():
    r.zadd('sset_1', '11', 1, '22', 2, '33', 3, '44', 4, '55', 5, '66', 6, '66', 7)  # 在name对应的有序集合中添加元素
    print(r.zcard('sset_1'))  # 获取name对应的有序集合元素的数量
    print(r.zcount('sset_1', 1, 2))  # 获取name对应的有序集合中分数 在 [min,max] 之间的个数
    r.zincrby('sset_1', '11', amount=5)  # 自增name对应的有序集合的 name 对应的分数
    print(r.zrange('sset_1', 0, -1, desc=False, withscores=True))  # 值11被排序到最后;此处表示按元素的值升序排列
    
    print(r.zrank('sset_1', 33))  # 获取某个值在 name对应的有序集合中的排行(从 0 开始)
    
    r.zrem('sset_1', '66')  # 删除name对应的有序集合中值是values的成员
    print(r.zrange('sset_1', 0, -1, desc=False, withscores=True))
    
    r.zremrangebyrank('sset_1', 0, 1)  # 根据排行范围删除
    print(r.zrange('sset_1', 0, -1, desc=False, withscores=True))
    
    r.zremrangebyscore('sset_1', 4.5, 5.5)  # 根据分数范围删除
    print(r.zrange('sset_1', 0, -1, desc=False, withscores=True))
    
    print(r.zscore('sset_1', 11))  # 获取name对应有序集合中 value 对应的分数
    
    r.zadd("sset_0", "a1", 6, "a2", 2, "a3", 5)
    r.zadd('sset_1', a1=7, b1=10, b2=5)
    '''
        获取两个有序集合的交集并放入dest集合,如果遇到相同值不同分数,则按照aggregate进行操作
        aggregate的值为: SUM  MIN  MAX
    '''
    r.zinterstore('sset_2', ('sset_0', 'sset_1'), aggregate='Sum')
    
    print(r.zrange('sset_2', 0, -1, desc=False, withscores=True))
    
    
    


'''
五、哈希 hashes

Redis 数据库hash数据类型是一个string类型的key和value的映射表,适用于存储对象。
redis 中每个hash可以存储键值对多达40亿。
Python的redis模块实现了Redis哈希(Hash)命令行操作的几乎全部命令,
包括HDEL、HEXISTS、HGET、HGETALL、HINCRBY、HKEYS、HLEN 、HMGET 、HMSET 、HSET 、HSETNX 、HVALS 、HINCRBYFLOAT等命令。
函数说明如下:

1、HDEL:删除对应哈希(Hash)表的指定键(key)的字段,hdel(self, name, key)
2、HEXISTS:检测哈希(Hash)表对应键(key)字段是否存在,返回布尔逻辑,hexists(self, name, key)
3、HGET:获取哈希(Hash)指定键(key)对应的值,hget(self, name, key)
4、HGETALL:获取哈希(Hash)表的键-值对(key-value pairs),返回python字典类型数据,hgetall(self, name)
5、HINCRBY:为哈希表(Hash)指定键(key)对应的值(key)加上指定的整数数值(int,可为负值)hincrby(self>, name, key, amount=1),Redis 中本操作的值被限制在 64 位(bit)有符号数字。
6、HKEYS:返回哈希表(Hash)对应键(key)的数组(Python称之为列表List),hkeys(self, name)
7、HLEN: 获取哈希表(Hash)中键-值对(key-value pairs)个数,hlen(self, name)
8、HMGET:获取哈希表(Hash)中一个或多个给点字段的值,不存在返回nil(Redis命令行)/None(Python),hmget(self, name, keys),其中keys可以为列表(list)
9、HMSET:设置多个键-值对(key-value pairs)到哈希表(Hash)中,python输入值(mapping)为字典(dictionary)类型,hmset(self, name, mapping)
10、HSET:为哈希表(Hash)赋值,若键(key)存在值(value)则覆盖,不存在则创建,hset(self, name, key, value)
11、HSETNX:为哈希表(Hash)不存值(value)的键(key)赋值,存在操作无效,对应值(value)无变化,hsetnx(self, name, key, value)
12、HVALS:返回哈希表(Hash)对应值(value)的列表,hvals(self, name)
13、HINCRBYFLOAT:为哈希表 key 中的指定字段的浮点数值加上增量 increment ,hincrbyfloat(self, name, key, amount=1.0)
'''
def test_redis_hash():
    r.hset('hash_1', 'k1', 'v1')  # hset(name, key, value),name对应的hash中设置一个键值对(不存在,则创建;否则,修改)
    print(r.hget('hash_1', 'k1'))
    r.hmset('hash_2', {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'})  # hmset(name, mapping),在name对应的hash中批量设置键值对
    print(r.hmget('hash_2', 'k2'))
    print(r.hgetall('hash_2'))  # 获取name对应hash的所有键值
    print(r.hlen('hash_2'))  # 获取name对应的hash中键值对的个数
    print(r.hkeys('hash_2'))  # 获取name对应的hash中所有的key的值
    print(r.hvals('hash_2'))  # 获取name对应的hash中所有的value的值
    print(r.hexists('hash_2', 'k4')) # 检查name对应的hash是否存在当前传入的key
    r.hdel('hash_2', 'k3')  # 将name对应的hash中指定key的键值对删除
    r.hset('hash_3', 'k1', 1)
    r.hincrby('hash_3', 'k1', amount=1)  # hincrby(name, key, amount=1),自增name对应的hash中的指定key的value的值,不存在则创建key=amount
    print(r.hgetall('hash_3'))



test_redis_string()
test_redis_list()
test_redis_set()
test_redis_sorted_set()
test_redis_hash()

  • Python使用redis存储对象
    使用pickle模块,在存入到redis中时调用dumps函数,获取后调用loads函数
import pickle
import redis


db = redis.Redis()

class Eg:
	a=1
	b=2
	def foo(self):
	    print('this is a foo')
	    
sen_data = pickle.dumps(Eg())
db.set(key,sen_data)
rec_data = db.get(key)
obj = pickle.loads(rec_data)

print(obj.a, obj.b)
obj.foo()

  • python调用dll

1、visual studio 创建动态库项目(动态库项目而不是其他新项目)假设项目名为ct。

2、创建好动态库项目,在项目内的源文件新建一个.cpp文件,用来实现c++这边的功能。
举例:add.cpp 代码如下

//add.cpp文件
extern "C" {
	__declspec(dllexport) int add(int x, int y) {
		return x + y;
	}
}

说明:核心暴露函数的代码片段:

extern "C" {
	__declspec(dllexport) xxx xxx(){}
}

xxx xxx(){} 为需要实现的函数功能。

3、在visual studio生成项目,相关项目文件目录下会有一个 ct.dll跟你项目名一样的dll文件。

4、dll目录下新建py文件,代码如下:

#py文件
import ctypes
lib = ctypes.cdll.LoadLibrary("ct.dll")
x=lib.add(3,4)
print(x)

即可实现py调用dll。

备注:不同版本的python在LoadLibrary()函数对dll文件的引入路径有点区别,目前已知python3.10.x引用同目录下dll样式:LoadLibrary(“./ct.dll”)

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值