全局数据在Python包中模块间管理方法探讨

news2024/11/23 18:51:54

在开发大型 Python 应用程序时,有时需要多个模块共享和管理全局数据。如何优雅地在 Python 包内的不同模块间共享全局数据是一个常见的设计问题。我们希望避免全局变量的混乱和难以维护的代码,但同时能够安全、高效地管理这些共享数据。

下面我们将探讨几种常用的全局数据管理方法,以及如何在模块间合理共享和修改全局数据。

在这里插入图片描述

1、问题背景

在Python或其他编程语言中,如何管理跨包的模块中全局数据?在设计语言Heron的包和模块系统时,我受Python模块系统启发很大。Python有丰富的模块选择,这似乎对其成功有很大贡献。其中存在疑问的是,如果在一个Python模块中包含了两个不同的已编译包,会发生什么情况:是制作数据副本还是共享数据?与此相关的是一系列侧问题:

我假设包在Python中可以被编译,是否正确?

模块数据复制或共享的两种方法有什么优缺点?

从Python社区的角度来看,Python的模块系统存在哪些众所周知的问吗?例如,是否有正在考虑用于增强模块/包的PEP?

Python模块/包系统中哪些方面对编译语言来说行不通?

2、解决方案

回答1:

a. Python代码被词法分析并编译成Python特定指令,但没有被编译成机器可执行代码。".pyc"文件会在运行与现有.pyc时间戳不匹配的Python代码时自动创建。可以关闭此功能。可以使用dis模块来查看这些指令。
b. 导入模块时,它将在其命名空间中(从上到下)执行,并将该命名空间全局缓存。从另一个模块导入时,该模块不会再次执行。请记住,def只是一个语句。可能需要在代码中放置一个print(‘compiling this module’)语句来跟踪它。

这取决于具体情况。
最近有一些增强,主要围绕指定需要加载哪些模块。模块可以有相对路径,以便一个大项目中有多个具有相同名称的模块。
Python本身不能用于编译语言。在Google中搜索“unladen swallow blog”,查看试图加速语言的磨难。“a = sum(b)”在执行之间可以改变含义。撇开极端情况,模块系统在源代码和编译库系统之间形成了一个很好的桥梁。这种方法很有效,Python轻松地封装C代码(swig等)有所帮助。

示例.py:
print “Creating %s module.” % name

def show_def(f):
print “Creating function %s.%s.” % (name, f.name)
return f

@show_def
def a():
print “called: %s.a” % name

交互式会话:

import example

先检查sys.modules[‘example’]

由于它不存在,可以找到example.py并将它“编译”到example.pyc

(由于example.pyc不存在,如果它是过时的,也会发生同样的情况,等等)

Creating example example module. # 执行模块代码
Creating function example.a. # 执行def语句

example.a()
called: example.a
import example

找到sys.modules[‘example’],将局部变量example分配给该对象

没有 ‘Creating …’ 输出

d = {“name”: “fake”}
exec open(“example.py”) in d

本次会话中的第一次导入与此非常相似

它创建一个模块对象(具有__dict__),初始化其中的几个变量

builtins, name__和其他变量—包的__init

模块也有自己的变量—查看some_module.dict.keys()或

dir(some_module))

并执行example.py中的代码(或存储在example.pyc中的代码对象)

Creating fake module. # 执行模块代码
Creating function fake.a. # 执行def语句

d.keys()
[‘builtins’, ‘name’, ‘a’, ‘show_def’]
d’a’
called: fake.a

解答2:
模块是Python中唯一真正的全局对象,所有其他全局数据都基于模块系统(它使用sys.modules作为注册表)。包只是具有导入子模块的特殊语义的模块。“在某种意义上讲,编译”一个.py文件成.pyc或.pyo并不是大多数语言所了解的编译:它只检查语法并创建一个在解释器中执行时创建模块对象的代码对象。

示例.py:
print “Creating %s module.” % name

def show_def(f):
print “Creating function %s.%s.” % (name, f.name)
return f

@show_def
def a():
print “called: %s.a” % name

交互式会话:

import example

先检查sys.modules[‘example’]

由于它不存在,可以找到example.py并将它“编译”到example.pyc

(由于example.pyc不存在,如果它是过时的,也会发生同样的情况,等等)

Creating example example module. # 执行模块代码
Creating function example.a. # 执行def语句

example.a()
called: example.a
import example

找到sys.modules[‘example’],将局部变量example分配给该对象

没有 ‘Creating …’ 输出

d = {“name”: “fake”}
exec open(“example.py”) in d

本次会话中的第一次导入与此非常相似

它创建一个模块对象(具有__dict__),初始化其中的几个变量

builtins, name__和其他变量—包的__init

模块也有自己的变量—查看some_module.dict.keys()或

dir(some_module))

并执行example.py中的代码(或存储在example.pyc中的代码对象)

Creating fake module. # 执行模块代码
Creating function fake.a. # 执行def语句

d.keys()
[‘builtins’, ‘name’, ‘a’, ‘show_def’]
d’a’
called: fake.a

你的问题:

它们在某种意义上是编译的,但如果你熟悉C编译器的工作方式,那么它们与你的预期不符。
如果数据是不可变的,那么复制是可行的,除了对象标识符(Python中的is运算符和id())外,它与共享应该是无法区分的。

导入可能会或可能不会执行代码(它们总是会将局部变量分配给一个对象,但这不会产生问题),并且可能会或可能不会修改sys.modules。必须小心不要在多线程中导入,通常最好在每个模块的顶部进行所有导入:这将导致一个级联图,以便立即完成所有导入,然后__main__继续并执行真正的任务。

我不知道当前是否有任何PEP,但已经有很多复杂的机制到位。例如,包可以具有__path__属性(实际上是一个路径列表),因此子模块不必位于同一目录中,这些路径甚至可以在运行时计算!(请看下面的mungepath包示例。)你可以拥有自己的导入挂钩,在函数中使用import语句,直接调用__import__,而且我不会感到惊讶会找到2-3其他独特的方法来使用包和模块。

导入系统的一个子集可以在传统编译语言中使用,只要它类似于C的#include即可。可以在编译器中运行“第一级”执行(创建模块对象),并编译那些结果。然而,这样做有显着的缺点,等于模块级代码和运行时执行的函数的分离执行上下文(有些函数必须在这两个上下文中运行!)。(请记住在Python中每条语句都在运行时执行,即使是def和class语句也是如此。)

我认为这是传统编译语言将“顶层”代码限制为类、函数和对象声明、消除第二个上下文的主要原因。即使在那时,你也会遇到C/C++(和其他语言)中全局对象的初始化问题,除非小心地管理。

mungepath/init.py:
print path
path.append(“.”) # CWD,在非示例代码中会不同
print path
from . import example # 这是上面示例的example.py,不在mungepath/中

注意这是一个退化的情况,因为现在我们用两个名称来表示

“相同”的模块:example和mungepath.example,但它们实际上是

具有不同函数的不同模块(使用 ‘is’ 或 ‘id()’ 来验证)

交互式会话:

import example
Creating example module.
Creating function example.a.
example.dict.keys()
[‘a’, ‘builtins’, ‘file’, ‘show_def’, ‘package’,
name’, ‘doc’]
import mungepath
[‘mungepath’]
[‘mungepath’, ‘.’]
Creating mungepath.example module.
Creating function mungepath.example.a.
mungepath.example.a()
called: mungepath.example.a
example is mungepath.example
False
example.a is mungepath.example.a
False

解答3:
全局数据在解释器级别进行控制。

“包”可以被编译,因为包只是可以编译的模块的集合。
我不确定我在给定数据确定的作用域下理解。

在 Python 包中管理全局数据的方法有多种,具体选择取决于应用的规模和需求:

  1. 简单项目:可以使用专门的模块存储全局数据,适用于全局数据较少且简单的情况。
  2. 面向对象项目:使用单例模式是一个更优雅的选择,尤其在需要数据封装时。
  3. 多线程/异步项目contextvars 提供了线程安全的全局数据管理方法。
  4. 结构化数据:使用 dataclasses 或配置对象可以提供更强的数据结构化管理。
  5. 跨进程:环境变量适合用于跨进程或容器化应用。

根据项目的需求和复杂度,选择合适的全局数据管理方法能够提高代码的可维护性和可扩展性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2196761.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

低代码赋能汽车制造产业链场景系列

当前汽车行业数字化智能化转型浪潮下,整车及其上下游产业链的协同创新正变得至关重要。头部车企与上下游供应链企业正逐步解决在生产管理、业务互通、系统集成等方面的痛点与挑战。电动化、智能化、网联化作为汽车产业的三大趋势,正共同推动未来汽车产业…

MS SQL Server 实战 统计与汇总重复记录

目录 需求 范例运行环境 数据样本设计 功能实现 上传EXCEL文件到数据库 分组统计 SQL 语句 分组汇总 SQL 语句 having 语句过滤最终统计结果 小结 需求 在日常的数据管理应用中,统计和汇总重复记录的情况是经常遇到的一个问题,然后我们会根据统…

文字转语音软件哪个好?这里告诉你

在英语学习的众多环节中,听力练习无疑是至关重要的一环。 然而,平时缺乏英语环境,如何高效地利用身边的英语材料进行听力训练呢?这时,英语文字转语音工具就很重要了! 今天,就为大家介绍五款优…

【C++】认识匿名对象

文章目录 目录 文章目录前言一、对匿名对象的解读二、匿名对象的对象类型三、匿名对象的使用总结 前言 在C中,匿名对象是指在没有呗命名的情况下创建的临时对象。它们通常在单个语句中执行一系列操作或调用某个函数,并且不需要将结果存放进变量中。 匿名…

常用动词敬语形式大揭秘,柯桥零基础日语培训

一、常用动词的敬语形式 1. する(做) • 尊敬语: なさる (Nasaru) 例:社長はよく運動をなさいます。 (社长经常锻炼。) • 谦逊语: いたす (Itasu) 例:この仕事は私がいたします。 &…

Java解析图形mdb矢量mdb

Java解析图形mdb矢量mdb 背景:项目中需要解析图形mdb,同事积累下的代码无法读取复杂图形;终于在某位大佬的博客下发现新的 解析方法,特此整理记录下。原理:jackcess(assess提供解析mdb属性)、es…

C++模拟实现二叉搜索树

目录 1.二叉搜索树的概念 2.二叉搜索树的性能分析 3.二叉搜索树的结构和中序遍历 3.1二叉搜索树中节点的结构 3.2二叉搜索树的结构 3.3中序遍历 4.二叉搜索树的插入 5.二叉搜索树的查找 6.二叉树搜索树的删除 7. 二叉搜索树的默认成员函数 8.参考代码 9.二叉搜…

常见的图像处理算法:Canny边缘检测

一、Canny边缘检测算子的由来 Canny 边缘检测算子是一种多级检测算法。1986 年由 John F. Canny 提出,同时提出 了边缘检测的三大准则: 1、低错误率的边缘检测:检测算法应该精确地找到图像中的尽可能多的边缘,尽可能的减少漏检…

【一起学Rust | 框架篇 | Tauri2.0框架】高级概念之安全特性的权限与能力

文章目录 前言一、开发前准备1. 准备项目2. 需求分析1. 监听系统热键2. 切换窗口无边框3. 切换窗口全屏 二、安装插件三、前端实现功能四、配置权限 前言 当前时间为 2024 年 9 月,距离Tauri 2.0 的 RC 版本发布迄今已近一个月。从 Tauri 官方渠道可以看出&#xf…

李飞飞:我不知道什么是AGI

图片来源:Stanford University 你对人工通用智能(AGI)感到困惑吗?这就是 OpenAI 执着于最终以“造福全人类”的方式创造的东西。你可能想认真对待他们,因为他们刚筹集了 66 亿美元以更接近这个目标。 但如果你仍然在…

揭秘Sui存储基金:灵活且可持续的链上数据管理解决方案

链上数据存储的方法常常被忽视,因为所使用的机制通常是传统和常见的。然而,在去中心化网络中,数据存储对确保数据完整性和长期可访问性至关重要。Sui的链上存储与其他区块链有所不同。 Sui存储基金是为了解决链上数据永久存储问题而设计的核…

企业架构系列(16)ArchiMate第14节:实施和迁移视角

在企业架构中,为了有效地规划和管理架构的变更与实施,通常会使用不同的视角来描述架构的不同方面。本篇涉及到三个主要视角:项目视角、迁移视角以及实施与迁移视角。 一、实施和迁移视角概览 1.项目视角 元素与关系:关注项目本身…

“网络安全等级保护测评入门:基础概念与重要性“

网络安全等级保护测评(简称“等保测评”)是依据国家网络安全等级保护制度,对信息系统安全等级进行评估和评定的过程。它是提高信息系统安全性、保障信息安全的重要手段。以下是关于等保测评的基础概念与重要性的详细解读: 一、等…

【钱拿不回来了,中介说开源吧】《刚体旋转的四元数模型及捷联惯性导航系统中定向算法》

《刚体旋转的四元数模型及捷联惯性导航系统中定向算法》 1. 摘要 本文深入探讨了四元数在刚体旋转描述中的核心作用以及其在捷联惯性导航系统(SINS)中确定方向的算法。详细阐述了四元数的理论基础、数学性质和实际应用优势,包括与卡丹角和欧…

小红书AI商单变现,单月收入10000+,真猛!

AI相关的话题在这两年来一直很火爆,很多行业也纷纷和AI结合起来, 从而达到更好的变现效果,这也是未来的发展趋势, 有这个工具确实能给我们的工作和生活带来一些便利 之前也拆解过很多类似的玩法, 比如AI古诗词、数…

软件测试之压力测试

🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 压力测试 压力测试是一种软件测试,用于验证软件应用程序的稳定性和可靠性。压力测试的目标是在极其沉重的负载条件下测量软件的健壮性和错误处理能力&…

GSLAM——一个通用的SLAM架构和基准

GSLAM: A General SLAM Framework and Benchmark 开源地址 摘要: SLAM技术最近取得了许多成功,并吸引了高科技公司的关注。然而,如何同一现有或新兴算法的界面,一级有效地进行关于速度、稳健性和可移植性的基准测试仍然是问题。本…

芯片干货 | 同步内置MOS升压恒压5V/2A芯片FP6276B,输入限流可调

芯片概述 FP6276B是一个具有PWM/PSM控制的电流模式增压直流-直流转换器。它的PWM电路内置40mΩ高侧开关和40mΩ低侧开关使该调节器高高效。内部补偿网络还将外部组件计数最小化到只有6个。一个内部的0.6V电压被连接到误差放大器的非反相输入作为精度参考电压。内置的软启动功能…

Llama 3.2 智能代理开发教程

构建研究代理可能很复杂,但使用 LangChain 和 Ollama,它会变得更加简单和模块化。 在本教程中,我们将向你展示如何基于Llama 3.2创建一个研究代理,该代理可以路由查询、执行网络搜索并使用工作流和 LLM 的组合生成详细响应。最后…

我的书第三次重印啦,做一波活动,参与可抽现金红包~

大家好,我是拭心,好久不见。 四月份我的《Android 性能优化入门与实战》顺利出版,在朋友们帮忙宣传下,初印的两三千册很快卖完,四月份第二次重印,五个月后,又迎来了第三次重印。 这样的销量算不…