在Python3中使用Python2工具架

在Python3中使用Python2工具架,python,python-2.7,python-3.x,Python,Python 2.7,Python 3.x,我将数据存储在使用python 2.7创建的工具架文件中 当我尝试从python 3.4访问该文件时,出现了一个错误: >>> import shelve >>> population=shelve.open('shelved.shelf') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:\Python34\lib\s

我将数据存储在使用python 2.7创建的工具架文件中

当我尝试从python 3.4访问该文件时,出现了一个错误:

>>> import shelve
>>> population=shelve.open('shelved.shelf')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python34\lib\shelve.py", line 239, in open
    return DbfilenameShelf(filename, flag, protocol, writeback)
  File "C:\Python34\lib\shelve.py", line 223, in __init__
    Shelf.__init__(self, dbm.open(filename, flag), protocol, writeback)
  File "C:\Python34\lib\dbm\__init__.py", line 88, in open
    raise error[0]("db type could not be determined")
dbm.error: db type could not be determined
导入搁置 >>>人口=shelve.open('shelved.shelf') 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 文件“C:\Python34\lib\shelve.py”,第239行,打开 返回DbfilenameShelf(文件名、标志、协议、写回) 文件“C:\Python34\lib\shelve.py”,第223行,在\uu init中__ Shelf.\uuuu init\uuuuu(self,dbm.open(文件名,标志),协议,写回) 文件“C:\Python34\lib\dbm\\uuuuu init\uuuuuu.py”,第88行,打开 引发错误[0](“无法确定数据库类型”) dbm.error:无法确定数据库类型
在Python2.7中,我仍然能够访问shelf,没有问题,因此似乎存在向后兼容性问题。有没有办法用新的python版本直接访问旧格式?

编辑:您可能需要重命名数据库。继续读

看来这里的罪魁祸首不是pickle
shelve
还依赖于
anydbm
(Python 2.x)或
dbm
(Python 3)来创建/打开数据库并存储pickle信息

我使用以下命令(手动)创建了一个数据库文件:

# Python 2.7
import anydbm
anydbm.open('database2', flag='c')

在这两种情况下,它都会创建相同类型的数据库(可能依赖于发行版,这是在Debian 7上):

anydbm
可以毫无问题地打开
database3.db
,正如预期的那样:

>>> anydbm.open('database3')
<dbm.dbm object at 0x7fb1089900f0>
除非我将数据库名称的名称更改为
database2.db

$ mv database2 database2.db
$ python3
>>> import dbm
>>> dbm.open('database2')
<_dbm.dbm object at 0x7fa7eaefcf50>
$mv database2 database2.db
$python3
>>>导入数据库管理
>>>dbm.open('database2')
因此,我怀疑
dbm
模块上存在回归,但我还没有检查文档。它的目的可能是:-


注意:在我的例子中,扩展名是
.db
,但这取决于默认情况下
dbm
使用的数据库!使用Python3创建一个空的工具架,以确定您使用的是哪一个工具架以及它期望的是什么。

shelve模块使用Python的工具架,在不同版本的Python之间访问时,可能需要协议版本

请尝试提供协议版本2:

population = shelve.open('shelved.shelf', protocol=2)
根据文件:

Python2.3中引入了协议版本2。它提供了对新样式类更有效的酸洗。参考PEP 307,了解协议2带来的改进信息


这很可能是原始序列化(或酸洗)中使用的协议。

我认为不可能将Python2工具架与Python3的
工具架一起使用。底层文件完全不同,至少在我的测试中是这样

Python2*中,工具架被表示为一个文件,文件名为您最初提供的文件名

Python 3*中,工具架由三个文件组成:
filename.bak
filename.dat
filename.dir
。如果没有这些文件,Python 3库将无法打开工具架(尽管看起来只有
.dat
文件足以打开,如果不是实际读取的话)

已经概述了为什么会出现这种情况——存储搁置数据时使用的底层数据库模块可能存在问题。数据库可能是向后兼容的,但我不知道,快速搜索也没有找到任何明显的答案

我认为由
dbm
实现的一些可能的数据库可能是向后兼容的,而其他的则不是:这可能是这里答案之间存在差异的原因,在这里,有些人,但不是所有人,能够通过指定协议直接打开旧的数据库



*在我测试过的每台机器上,使用Python2.7.6与Pythons 3.2.5、3.3.4和3.4.1,正如我现在所理解的,以下是导致我的问题的路径:

  • 最初的工具架是在Windows中使用Python 2创建的
  • Python2 Windows默认将bsddb作为搁置的基础数据库,因为dbm在Windows平台上不可用
  • Python 3不随bsddb提供。底层数据库是Python 3 for Windows中的dumbdbm
起初,我考虑为Python3安装第三方bsddb模块,但很快就变成了一件麻烦事。然后,每当我需要在新机器上使用同一个shelf文件时,这似乎都是一个反复出现的麻烦。因此,我决定将文件从bsddb转换为dumbdbm,我的python 2和python 3安装都可以读取该文件

我在Python 2中运行了以下内容,该版本同时包含bsddb和DBM:

import shelve
import dumbdbm

def dumbdbm_shelve(filename,flag="c"):
    return shelve.Shelf(dumbdbm.open(filename,flag))

out_shelf=dumbdbm_shelve("shelved.dumbdbm.shelf")
in_shelf=shelve.open("shelved.shelf")

key_list=in_shelf.keys()
for key in key_list:
    out_shelf[key]=in_shelf[key]

out_shelf.close()
in_shelf.close()

到目前为止,dumbdbm.shelf文件看起来还可以,等待再次检查内容。

是的,我可以复制这个。你不能用这个工具把源代码转换成3吗?对不起,似乎不行——另外一个问题是,你的平台对
anydbm
dbm
使用不同的默认数据库。在我的例子中也是如此,但是@HenryKeiterI发现一篇帖子指出问题可能是因为Python3中缺少Berkeley db支持。试图找出如何安装第三方模块,看看这是否有帮助。引用的帖子可能是肯定的——然而,这开始变成一种痛苦。安装说明告诉Windows用户运行安装程序,但是找不到Python3的安装程序。当我开始看到使用VisualStudio编译Berkeley db的说明时,我决定是时候制定计划B了:)你在否决之前测试过这个吗?Python3
protocol=2
确实有效。@JacobBudin当然我测试过了
protocol=2
会产生完全相同的错误。@HenryKeiter仅仅因为您的工具架接口与Python主要版本不同,并不意味着对每个人都是如此。@JacobBudin在asker中指定了2.7和3.X<代码>协议=2
$ mv database2 database2.db $ python3 >>> import dbm >>> dbm.open('database2') <_dbm.dbm object at 0x7fa7eaefcf50>
population = shelve.open('shelved.shelf', protocol=2)
import shelve
import dumbdbm

def dumbdbm_shelve(filename,flag="c"):
    return shelve.Shelf(dumbdbm.open(filename,flag))

out_shelf=dumbdbm_shelve("shelved.dumbdbm.shelf")
in_shelf=shelve.open("shelved.shelf")

key_list=in_shelf.keys()
for key in key_list:
    out_shelf[key]=in_shelf[key]

out_shelf.close()
in_shelf.close()