Python: 将版本号和数据保存到 pickle 文件中
Python: Saving version number and data into pickle file
我正在将一些数据序列化到 pickle 文件中。不幸的是,数据的结构可能会改变。因此,我在代码中有一个静态版本号,如果数据结构发生变化,它会递增。在这种情况下,泡菜文件中的数据是无效的,应该被丢弃。
因此我试图保存一个由数据和版本号组成的元组。但是从 pickle 恢复它会引发 UnicodeDecodeError:
UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0: ordinal not in range(128)
我想知道您将如何包含版本号?将它嵌入文件路径是一种选择,但要复杂得多。这是我的代码:
#%% Create a dataframe
import pandas as pd
values = {'Latitude': {0: 47.021503365600005,
1: 47.021503365600005,
2: 47.021503365600005,
3: 47.021503365600005,
4: 47.021503365600005,
5: 47.021503365600005},
'Longitude': {0: 15.481974060399999,
1: 15.481974060399999,
2: 15.481974060399999,
3: 15.481974060399999,
4: 15.481974060399999,
5: 15.481974060399999}}
df = pd.DataFrame(values)
df.head()
#%% Save the dataframe including a version number
import pickle
VERSION = 1
file_path = 'tmp.p'
with open(file_path, 'wb') as f:
pickle.dump((df, VERSION), f)
#%% Load the dataframe including the original verison number
try:
with open(file_path, 'r') as f:
df, version = pickle.load(f)
except ValueError as ex:
print (ex)
version = -1
#%% Compare version numbers
if version != VERSION:
print ('Version do not match')
如果你真的想使用 pickle 存储你的对象,你可以像这样在 csv 文件中存储一个元组:
with open('my_file.csv', 'w') as fd:
writer = csv.writer(fd)
writer.writerow([version_number, pickle.dumps(fd)])
您将只有一个文件(而不是两个,正如您在评论中所说的那样),即 csv 文件。 pickle.dumps
returns 一个字符串,而 pickle.loads
从一个字符串加载对象,比较 https://docs.python.org/3/library/pickle.html#pickle.dumps and https://docs.python.org/3/library/pickle.html#pickle.loads
然后你这样读数据
with open('my_file.csv') as fd:
reader = csv.reader(fd)
row = csv.readrow()
fd_class = get_fd_class_by_version(row[0])
fd = pickle.loads(row[1])
这里 get_fd_class_by_version
是一种工厂,returns class 依赖于您存储的版本。
您用于打开文件进行读取操作的模式可能有问题。
对于写入,您使用 wb
(以二进制模式写入),但对于读取,您使用 r
(不以二进制模式读取,省略了 b
)。
open(file_path, 'rb') as f
如果您使用 Windows。
,这可能是个问题
详情请看这里:https://docs.python.org/2/tutorial/inputoutput.html#reading-and-writing-files
我正在将一些数据序列化到 pickle 文件中。不幸的是,数据的结构可能会改变。因此,我在代码中有一个静态版本号,如果数据结构发生变化,它会递增。在这种情况下,泡菜文件中的数据是无效的,应该被丢弃。
因此我试图保存一个由数据和版本号组成的元组。但是从 pickle 恢复它会引发 UnicodeDecodeError:
UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0: ordinal not in range(128)
我想知道您将如何包含版本号?将它嵌入文件路径是一种选择,但要复杂得多。这是我的代码:
#%% Create a dataframe
import pandas as pd
values = {'Latitude': {0: 47.021503365600005,
1: 47.021503365600005,
2: 47.021503365600005,
3: 47.021503365600005,
4: 47.021503365600005,
5: 47.021503365600005},
'Longitude': {0: 15.481974060399999,
1: 15.481974060399999,
2: 15.481974060399999,
3: 15.481974060399999,
4: 15.481974060399999,
5: 15.481974060399999}}
df = pd.DataFrame(values)
df.head()
#%% Save the dataframe including a version number
import pickle
VERSION = 1
file_path = 'tmp.p'
with open(file_path, 'wb') as f:
pickle.dump((df, VERSION), f)
#%% Load the dataframe including the original verison number
try:
with open(file_path, 'r') as f:
df, version = pickle.load(f)
except ValueError as ex:
print (ex)
version = -1
#%% Compare version numbers
if version != VERSION:
print ('Version do not match')
如果你真的想使用 pickle 存储你的对象,你可以像这样在 csv 文件中存储一个元组:
with open('my_file.csv', 'w') as fd:
writer = csv.writer(fd)
writer.writerow([version_number, pickle.dumps(fd)])
您将只有一个文件(而不是两个,正如您在评论中所说的那样),即 csv 文件。 pickle.dumps
returns 一个字符串,而 pickle.loads
从一个字符串加载对象,比较 https://docs.python.org/3/library/pickle.html#pickle.dumps and https://docs.python.org/3/library/pickle.html#pickle.loads
然后你这样读数据
with open('my_file.csv') as fd:
reader = csv.reader(fd)
row = csv.readrow()
fd_class = get_fd_class_by_version(row[0])
fd = pickle.loads(row[1])
这里 get_fd_class_by_version
是一种工厂,returns class 依赖于您存储的版本。
您用于打开文件进行读取操作的模式可能有问题。
对于写入,您使用 wb
(以二进制模式写入),但对于读取,您使用 r
(不以二进制模式读取,省略了 b
)。
open(file_path, 'rb') as f
如果您使用 Windows。
,这可能是个问题详情请看这里:https://docs.python.org/2/tutorial/inputoutput.html#reading-and-writing-files