热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

读取pickle文件时的AttributeError

如何解决《读取pickle文件时的AttributeError》经验,为你挑选了1个好方法。

当我在spyder(python 3.6.5)上读取我的.pkl文件时出现以下错误:

IN: with open(file, "rb") as f:
       data = pickle.load(f)  

Traceback (most recent call last):

 File "", line 2, in 
   data = pickle.load(f)

AttributeError: Can't get attribute 'Signal' on 

上下文:

我的程序由一个文件组成:program.py 在程序中,Signal定义了一个类以及许多函数.下面提供了该计划的简要概述:

import numpy as np
import _pickle as pickle
import os

# The unique class
class Signal:
    def __init__(self, fq, t0, tf):
        self.fq = fq
        self.t0 = t0
        self.tf = tf
        self.timeline = np.round(np.arange(t0, tf, 1/fq*1000), 3)

# The functions
def write_file(data, folder_path, file_name):
    with open(join(folder_path, file_name), "wb") as output:
        pickle.dump(data, output, -1)

def read_file(folder_path, file_name):
    with open(join(folder_path, file_name), "rb") as input:
        data= pickle.load(input)
    return data

def compute_data(# parameters):
    # do stuff

该函数compute_data将返回表单元组的列表:

data = [((Signal_1_1, Signal_1_2, ...), val 1), ((Signal_2_1, Signal_2_2, ...), val 2)...]

当然,Signal_i_k是一个对象Signal.此列表将以.pkl格式保存.而且,我正在使用不同的compute_data函数参数进行大量迭代.许多迭代将使用过去的计算数据作为起点,因此将读取相应的和所需的.pkl文件.

最后,我同时使用多台计算机,每台计算机都将计算数据保存在本地网络上.因此,每台计算机都可以访问其他计算机生成的数据并将其用作起点.

回到错误:

我的主要问题是,当我通过双击文件或通过windows cmd或PowerShell启动程序时,我从未遇到此错误.该程序永远不会崩溃抛出此错误并运行没有明显的问题.

但是,我无法在spyder中读取.pkl文件.每次我尝试,都会抛出错误.

知道为什么我有这种奇怪的行为吗?

谢谢!



1> Dunes..:

当你把东西转储成a时,pickle你应该避免在主模块中声明的pickling类和函数.您的问题是(部分)因为您的程序中只有一个文件.pickle是惰性的,不会序列化类定义或函数定义.相反,它保存了如何查找类(它所在的模块及其名称)的参考.

当python直接运行脚本/文件时,它将程序作为__main__模块运行(无论其实际文件名如何).但是,当加载文件而不是主模块时(例如,当您执行类似操作时import program),其模块名称将基于其名称.所以program.py被召唤program.

当您从命令行运行时,您正在执行前者,并调用该模块__main__.因此,pickle会创建对类的引用__main__.Signal.当spyder尝试加载pickle文件时,它会被告知导入__main__并查找Signal.但是,spyder的__main__模块是用来启动spyder而不是你的模块,program.py所以pickle找不到Signal.

您可以通过运行检查pickle文件的内容(-a打印每个命令的描述).从这里你会看到你的类被引用为__main__.Signal.

python -m pickletools -a file.pkl

你会看到类似的东西:

    0: \x80 PROTO      3              Protocol version indicator.
    2: c    GLOBAL     '__main__ Signal' Push a global object (module.attr) on the stack.
   19: q    BINPUT     0                 Store the stack top into the memo.  The stack is not popped.
   21: )    EMPTY_TUPLE                  Push an empty tuple.
   22: \x81 NEWOBJ                       Build an object instance.
   23: q    BINPUT     1                 Store the stack top into the memo.  The stack is not popped.
   ...
   51: b    BUILD                        Finish building an object, via __setstate__ or dict update.
   52: .    STOP                         Stop the unpickling machine.
highest protocol among opcodes = 2
解决方案

您可以使用多种解决方案:

    不要序列化__main__模块中定义的类的实例.最简单,最好的解决方案.而是将这些类移动到另一个模块,或编写一个main.py脚本来调用您的程序(两者都意味着在__main__模块中不再找到这样的类).

    写一个定制的derserialiser

    编写自定义序列化程序

以下解决方案将使用out.pkl由以下代码创建的pickle文件(在名为的文件中program.py):

import pickle

class MyClass:
    def __init__(self, name):
        self.name = name

if __name__ == '__main__':
    o = MyClass('test')
    with open('out.pkl', 'wb') as f:
        pickle.dump(o, f)

Custom Deserialiser解决方案

您可以编写一个客户反序列化器,它知道何时遇到__main__模块的引用您真正的意思是program模块.

import pickle

class MyCustomUnpickler(pickle.Unpickler):
    def find_class(self, module, name):
        if module == "__main__":
            module = "program"
        return super().find_class(module, name)

with open('out.pkl', 'rb') as f:
    unpickler = MyCustomUnpickler(f)
    obj = unpickler.load()

print(obj)
print(obj.name)

这是加载已创建的pickle文件的最简单方法.该程序是它将责任推到反序列化代码上,当序列化代码真正负责正确创建pickle文件时.

自定义序列化解决方案

与之前的解决方案相比,您可以确保任何人都可以轻松地对序列化的pickle对象进行反序列化,而无需了解自定义反序列化逻辑.为此,您可以使用该copyreg模块来通知pickle如何反序列化各种类.所以在这里,你要做的就是告诉pickle我们将所有__main__类的实例反序列化,就好像它们是program类的实例一样.您需要为每个类注册一个自定义序列化程序

import program
import pickle
import copyreg

class MyClass:
    def __init__(self, name):
        self.name = name

def pickle_MyClass(obj):
    assert type(obj) is MyClass
    return program.MyClass, (obj.name,)

copyreg.pickle(MyClass, pickle_MyClass)

if __name__ == '__main__':
    o = MyClass('test')
    with open('out.pkl', 'wb') as f:
        pickle.dump(o, f)


推荐阅读
  • Python 中使用 Numpy 实现高效对数加法运算函数 `logaddexp()` 的详解与应用 ... [详细]
  • 如何利用Python脚本实现钉钉自动化考勤打卡
    本文详细探讨了利用Python脚本实现钉钉自动化考勤打卡的方法。通过具体实例操作,解决了很多用户在实际应用中遇到的难题,帮助读者高效掌握这一实用技能。 ... [详细]
  • Python网络爬虫入门:利用urllib库进行数据抓取
    Python网络爬虫入门:利用urllib库进行数据抓取在数据科学和Web开发领域,Python凭借其简洁高效的特性成为首选语言。本文主要介绍了如何在Windows环境下使用Python的urllib库进行基本的网络数据抓取。考虑到命令行操作的不便,作者选择了Jupyter Notebook作为开发环境,不仅简化了配置过程,还提供了直观的数据处理和可视化功能。通过实例演示,读者可以轻松掌握urllib的基本用法,为深入学习网络爬虫技术打下坚实基础。 ... [详细]
  • 本文深入探讨了 Python Watchdog 库的使用方法和应用场景。通过详细的代码示例,展示了如何利用 Watchdog 监控文件系统的变化,包括文件的创建、修改和删除等操作。文章不仅介绍了 Watchdog 的基本功能,还探讨了其在实际项目中的高级应用,如日志监控和自动化任务触发。读者将能够全面了解 Watchdog 的工作原理及其在不同场景下的应用技巧。 ... [详细]
  • voc生成xml 代码
    目录 lxmlwindows安装 读取示例 可视化 生成示例 上面是代码,下面有调用示例 api调用代码,其实只有几行:这个生成代码也很简 ... [详细]
  • 深入解析Wget CVE-2016-4971漏洞的利用方法与安全防范措施
    ### 摘要Wget 是一个广泛使用的命令行工具,用于从 Web 服务器下载文件。CVE-2016-4971 漏洞涉及 Wget 在处理特定 HTTP 响应头时的缺陷,可能导致远程代码执行。本文详细分析了该漏洞的成因、利用方法以及相应的安全防范措施,包括更新 Wget 版本、配置防火墙规则和使用安全的 HTTP 头。通过这些措施,可以有效防止潜在的安全威胁。 ... [详细]
  • 深入学习 Python 中的 xlrd 模块:掌握 Excel 文件读取技巧
    本文深入探讨了 Python 中的 xlrd 模块,重点介绍了如何高效读取 Excel 文件(包括 xlsx 和 xls 格式)。同时,文章还详细讲解了 xlwt 模块在 Excel 文件写操作中的应用。此外,文中列举了常见单元格数据类型及其处理方法,为读者提供了全面的实践指导。 ... [详细]
  • 本项目在Java Maven框架下,利用POI库实现了Excel数据的高效导入与导出功能。通过优化数据处理流程,提升了数据操作的性能和稳定性。项目已发布至GitHub,当前最新版本为0.0.5。该项目不仅适用于小型应用,也可扩展用于大型企业级系统,提供了灵活的数据管理解决方案。GitHub地址:https://github.com/83945105/holygrail,Maven坐标:`com.github.83945105:holygrail:0.0.5`。 ... [详细]
  • 如何使用Python高效绘制矩形图形
    本文详细介绍了如何利用Python的Turtle库高效绘制矩形图形,适合初学者快速上手。通过具体示例代码,帮助读者理解Turtle库的基本绘图方法和技巧,同时探讨了在不同应用场景中绘制矩形的实际操作,为后续复杂图形的绘制打下坚实基础。 ... [详细]
  • 本文深入探讨了 Vue.js 中异步组件的应用与优化策略。首先,文章介绍了异步组件的基本概念及其在现代前端开发中的重要性。为了确保最佳实践,建议使用 Webpack 作为模块打包工具,因为 Browserify 默认不支持异步组件的加载。接着,详细解释了异步组件的使用方法,并提供了官方文档的相关链接以供参考。此外,文章还讨论了多种优化技巧,包括代码分割、懒加载和性能调优,以提升应用的整体性能和用户体验。 ... [详细]
  • 本题库精选了Java核心知识点的练习题,旨在帮助学习者巩固和检验对Java理论基础的掌握。其中,选择题部分涵盖了访问控制权限等关键概念,例如,Java语言中仅允许子类或同一包内的类访问的访问权限为protected。此外,题库还包括其他重要知识点,如异常处理、多线程、集合框架等,全面覆盖Java编程的核心内容。 ... [详细]
  • Python – 遍历日期序列的高效方法与技巧 ... [详细]
  • 如何构建基于Spring MVC框架的Java Web应用项目
    在构建基于Spring MVC框架的Java Web应用项目时,首先应创建一个新的动态Web项目。接着,需将必要的JAR包导入至WebContent/WEB-INF/lib目录下,确保包括Spring核心库及相关依赖。如遇缺失的JAR包,可向社区求助或通过Maven等工具自动下载。正确配置后,即可开始搭建应用结构与功能模块。 ... [详细]
  • Django框架下的对象关系映射(ORM)详解
    在Django框架中,对象关系映射(ORM)技术是解决面向对象编程与关系型数据库之间不兼容问题的关键工具。通过将数据库表结构映射到Python类,ORM使得开发者能够以面向对象的方式操作数据库,从而简化了数据访问和管理的复杂性。这种技术不仅提高了代码的可读性和可维护性,还增强了应用程序的灵活性和扩展性。 ... [详细]
  • Android目录遍历工具 | AppCrawler自动化测试进阶(第二部分):个性化配置详解
    终于迎来了“足不出户也能为社会贡献力量”的时刻,但有追求的测试工程师绝不会让自己的生活变得乏味。与其在家消磨时光,不如利用这段时间深入研究和提升自己的技术能力,特别是对AppCrawler自动化测试工具的个性化配置进行详细探索。这不仅能够提高测试效率,还能为项目带来更多的价值。 ... [详细]
author-avatar
留心6_136
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有