当前位置:首页 » 文件管理 » python模拟带时间缓存

python模拟带时间缓存

发布时间: 2024-09-18 18:30:55

python性能提升神器!lru_cache的介绍和讲解

我们经常谈论的缓存一词,更多的类似于将硬盘中的数据存放到内存中以至于提高读取速度,比如常说的redis,就经常用来做数据的缓存。 Python的缓存(lru_cache)是一种装饰在被执行的函数上,将其执行的结果缓存起来,当下次请求的时候,如果请求该函数的传参未变则直接返回缓存起来的结果而不再执行函数的一种缓存装饰器。

那它和redis的区别在哪?有什么优势?怎么使用? 下面为你讲解

1.现在我们先不使用缓存来写一个求两数之和的函数,并调用执行它两次:

执行结果

可以看到 test 被执行了两次,现在我们加上缓存再进行执行:

执行结果

可以看到 test 函数只被执行了一次,第二次的调用直接输出了结果,使用了缓存起来的值。

2.当我们使用递归求斐波拉契数列 (斐波那契数列指的是这样一个数列:0,1,1,2,3,5,8,它从第3项开始,每一项都等于前两项之和) 的时候,缓存对性能的提升就尤其明显了:

不使用缓存求第40项的斐波拉契数列

执行时间

使用缓存求第40项的斐波拉契数列:

执行时间

两个差距是非常明显的,因为不使用缓存时,相当于要重复执行了很多的函数,而使用了 lru_cache 则把之前执行的函数结果已经缓存了起来,就不需要再次执行了。

查看lru_cache源码会发现它可以传递两个参数: maxsize 、 typed :

代表被lru_cache装饰的方法最大可缓存的结果数量 (被装饰方法传参不同一样,则结果不一样;如果传参一样则为同一个结果) , 如果不指定传参则默认值为128,表示最多缓存128个返回结果,当达到了128个时,有新的结果要保存时,则会删除最旧的那个结果。如果maxsize传入为None则表示可以缓存无限个结果;

默认为false,代表不区分数据类型,如果设置为True,则会区分传参类型进行缓存,官方是这样描述的:

但在python3.9.8版本下进行测试,typed为false时,按照官方的测试方法测试得到的还是会被当成不同的结果处理,这个时候typed为false还是为true都会区别缓存,这与官方文档的描述存在差异:

执行结果

但如果是多参数的情况下,则会被当成一个结果:

执行结果

这个时候设置typed为true时,则会区别缓存:

执行结果

当传参个数大于1时,才符合官方的说法,不清楚是不是官方举例有误

当传递的参数是dict、list等的可变参数时,lru_cache是不支持的,会报错:

报错结果

缓存 缓存位置 是否支持可变参数 是否支持分布式 是否支持过期时间设置 支持的数据结构 需单独安装 redis 缓存在redis管理的内存中 是 是 是 支持5种数据结构 是 lru_cache 缓存在应用进程的内存中,应用被关闭则被清空 否 否 否 字典(参数为:key,结果为:value) 否

经过上面的分析,lru_cache 功能相对于redis来说要简单许多,但使用起来更加方便,适用于小型的单体应用。如果涉及的缓存的数据种类比较多并且想更好的管理缓存、或者需要缓存数据有过期时间(类似登录验证的token)等,使用redis是优于lru_cache的。

❷ 我用python写了一个脚本,是每隔30秒清理arp缓存,这样能够控制arp攻击吗求高手指教

不能。新的假arp信息来了,你还是会缓存错的mac地址啊。

❸ 软件开发模版缓存具体步骤怎么操作的呢

模板缓存就是把模版内容缓存到指定位置,只要涉及模版都可以设置缓存,

下面以py程序为例:
1.1 在导入搜索期间首先会被检查的地方是 sys.moles。 这个映射起到缓存之前导入的所有模块的作用(包括其中间路径)。 因此如果之前导入过 foo.bar.baz,则 sys.moles 将包含 foo, foo.bar 和 foo.bar.baz 条目。 每个键的值就是相应的模块对象。
在导入期间,会在 sys.moles 查找模块名称,如存在则其关联的值就是需要导入的模块,导入过程完成。 然而,如果值为 None,则会引发 MoleNotFoundError。 如果找不到指定模块名称,Python 将继续搜索该模块。
1.2 sys.moles 是可写的。删除键可能不会破坏关联的模块(因为其他模块可能会保留对它的引用),但它会使命名模块的缓存条目无效,导致 Python 在下次导入时重新搜索命名模块。键也可以赋值为 None ,强制下一次导入模块导致 MoleNotFoundError 。
但是要小心,因为如果你还保有对某个模块对象的引用,同时停用其在 sys.moles 中的缓存条目,然后又再次导入该名称的模块,则前后两个模块对象将 不是 同一个。 相反地,

1.3 importlib.reload() 将重用 同一个 模块对象,并简单地通过重新运行模块的代码来重新初始化模块内容。

1.1 在导入搜索期间首先会被检查的地方是 sys.moles。 这个映射起到缓存之前导入的所有模块的作用(包括其中间路径)。 因此如果之前导入过 foo.bar.baz,则 sys.moles 将包含 foo, foo.bar 和 foo.bar.baz 条目。 每个键的值就是相应的模块对象。
在导入期间,会在 sys.moles 查找模块名称,如存在则其关联的值就是需要导入的模块,导入过程完成。 然而,如果值为 None,则会引发 MoleNotFoundError。 如果找不到指定模块名称,Python 将继续搜索该模块。
1.2 sys.moles 是可写的。删除键可能不会破坏关联的模块(因为其他模块可能会保留对它的引用),但它会使命名模块的缓存条目无效,导致 Python 在下次导入时重新搜索命名模块。键也可以赋值为 None ,强制下一次导入模块导致 MoleNotFoundError 。
但是要小心,因为如果你还保有对某个模块对象的引用,同时停用其在 sys.moles 中的缓存条目,然后又再次导入该名称的模块,则前后两个模块对象将 不是 同一个。 相反地,

1.3 importlib.reload() 将重用 同一个 模块对象,并简单地通过重新运行模块的代码来重新初始化模块内容。

❹ Python 爬虫进阶篇——diskcahce缓存(二)

上一篇文章为大家介绍了diskcache的基础用法,本文将继续深入探讨diskcache的更多高级功能。

关于diskcache,它是一种基于SQLite数据库的缓存对象管理方式。SQLite是一个轻量级的基于磁盘的数据库,它不需要单独的服务器进程,并支持SQL查询。在上篇文章的源码截图上,你可以看到一些SQL语句的使用。

diskcache支持使用diskcache.FanoutCache自动分片基础数据库。分片是对数据进行水平分区,可以减少写入时的阻塞。尽管读和写不会互相阻碍,但写入会阻碍其他写入。分片的默认值为8。

以下是一个示例代码:

# 示例代码

在示例中,我们在diskcache_2文件夹中创建了一个具有四个分片和一秒超时的缓存。如果操作耗时超过一秒,它们将尝试中止操作。

那么每一个分片的大小是多少呢?分片的大小都是平均分配的,占总空间的四分之一。diskcache的默认大小为1GB。

diskcache提供了一个collections.deque兼容的双端队列diskcache.Deque。双端队列是堆栈和队列的一般化,可以在前后都可以进行快速访问和编辑,且可持久化,操作比较便捷。

以下是一个示例代码:

# 示例代码

运行结果如下:

Popleft 获取队列最前面的一个元素,pop获取末尾的一个元素;

Appendleft 在队列最开始添加一个元素,append 在末尾添加一个元素;

Extendleft 在队列最开始添加一个数组,extend在末尾添加一个数组;

那么deque的存储位置在哪里?可以使用以下命令查看队列的存储位置:

包括cache也是一个可以使用directory属性查看默认存储的位置;

那么如何指定directory呢?Deque的第二个参数指定存储位置,第一个参数为队列的初始值。或者可以直接指定参数名称,如下:

Index 类似于dict(字典),可持久化,使用也比较便捷。以下是一个示例:

# 示例代码

popitem表示获取最后一个键对值,并且删除,结果如下:

peekitem() 可传递last 参数是否获取最后一个,不会删除原始值;

setdefault(key,default) 可以给指定的key值设置默认值,在查找时可以预先设置一个默认值,防止key值不存在而抛出异常。

keys()与values()可以查找所有Index中的key值与value值,然而没有提供判断key值是否存在的方法,但是可以使用setdefault的方法自行封装。

Lock还记得上篇文章中提到的Lock锁吗?先看一下源码:

可以看到这里的锁用的就是cache的add方法的特性,源码中也给出了使用的方式:

从源码上看有一个while 死循环,直到add成功时才会被释放,这里处理的方式不是很好,可能会造成死锁,所以一般情况下,都会添加一个过期的时间,如下:

RLock还有一种RLock锁,与Lock锁的区别是RLock允许在同一线程中被多次acquire。而Lock却不允许这种情况。以下是一个示例:

结果是执行成功。

看一下源码:

从源码中可以看出,判断锁的条件是os.getpid()(进程pid)与threading.get_ident()(线程标识符),如果每次acquire时的pid与ident都相同的时,即可成功。那么就可以在相同的进程中无限次数的acquire,但是多少次acquire就得多少次的release,防止死锁。

那么是使用Lock还是RLock呢?这个要具体的看实际情况,并不是谁就一定好。

总结本次推文中介绍了diskcache中FanoutCache缓存分片、双端队列deque、Index、Lock以及RLock。

大家可以在实际中灵活运用,diskcache缓存的优势还是很大的,无需安装其他的模块,并且在文件管理器中能直接查看,还可以利用缓存的一些特性使用多线程的去实现业务等。

但是也是有缺点的,即受制于本地文件系统的限制。每个磁盘每个目录下的文件数量是有限制的,所以需要结合实际情况使用。

热点内容
删除云存储空间图库 发布:2024-09-19 19:59:18 浏览:639
荣耀三四的存储状况 发布:2024-09-19 19:54:19 浏览:99
事例数据库 发布:2024-09-19 19:54:11 浏览:206
php盒子 发布:2024-09-19 19:46:31 浏览:330
手机配置低和平精英如何提升技术 发布:2024-09-19 19:43:55 浏览:704
软件连不上服务器ip 发布:2024-09-19 19:15:49 浏览:723
服务器数据库如何建立 发布:2024-09-19 19:15:07 浏览:366
解压软件游戏 发布:2024-09-19 18:51:54 浏览:155
16新速腾配置怎么样有改进吗 发布:2024-09-19 18:47:20 浏览:338
脚本不管用 发布:2024-09-19 18:46:30 浏览:98