c++数据存储取代Python pickle
C++ data storage to replace Python pickle
我为今年秋天的Python编程课做了一个项目,有一个20个问题的风格的游戏,它将从用户的回答中学习。它使用基于对问题的是/否回答的树,并在到达"分支"末端时将每个决定的独特问题与动物一起腌制。
接近课程结束时,我们用c++做了一些工作(但我仍然是新手),我想在我的休息时间做一个c++版本的项目-这将使它更容易运行,例如,可执行文件。但是,我发现c++没有很多pickle风格的数据存储选项,而且我认为Boost也没有。序列化或Boost。Python特别适合这种情况。
有其他的选择吗,或者你有关于如何在c++中以另一种方式处理数据的建议?
原始的Python代码包括:
def check(self):
correct, lastnode = self.ask(self.root) #lastnode is the closest guess to the new animal
if correct =='n':
print("Rats! I didn't get it. Please help me improve.")
newanimal = AnTreeNode(input("What is your animal? "))
oldanimal = lastnode
newquestion = input("Please enter a yes/no question that wouldn select between a(n) %s
and a(n) %s: " %(newanimal,lastnode.data))+" "
direction = input("What would be the correct answer for a(n) %s? " %newanimal)
newnode = AnTreeNode(newquestion, parent = lastnode.parent)
if lastnode.parent == None:
self.root = newnode
elif lastnode.parent.yes == lastnode:
newnode.parent.yes = newnode
else:
newnode.parent.no = newnode
if direction == 'y':
newnode.yes, newnode.no = newanimal, oldanimal
elif direction == 'n':
newnode.yes, newnode.no = oldanimal, newanimal
newanimal.parent = newnode
oldanimal.parent = newnode
self.dumpTree()
elif correct == 'y':
print("I am soooo smart!")
def loadTree(self):
try:
f = open(self.treefile, "rb")
self.root = pickle.load(f)
except:
self.root = AnTreeNode("frog")
def dumpTree(self):
pickle.dump(self.root, open(self.treefile, 'wb'))
如果我将数据保存到文件或数组中,我想不出一种方法来使树工作(我并不是特别想创建一个动态数组,尽管我可以弄清楚是否在数组中存储东西最终会工作)。问题是我不确定如何引用一个特定的节点。还有其他的选择吗,或者关于如何使用它们的想法?谢谢!(圣诞快乐!)
实际上boost::序列化工作得很好,学习基本知识并不那么困难。
但是,您可能会考虑一些稍高级的库,如协议缓冲区。这样,您就可以拥有同时适用于python和c++版本的数据库。
EDIT: boost::python不是正确的解决方案,因为它只允许绑定。用它来保存数据将是一个真正的痛苦。
Boost serialize允许序列化(然后很容易地保存在磁盘上)c++结构。请尝试文档中的示例。
协议缓冲区是一种序列化格式,允许以二进制格式交换数据。格式定义良好,因此您可以从不同的语言读/写和交换数据。在代码中更容易操作,例如XML: http://code.google.com/p/protobuf/然而,我认为它需要比boost::serialize更多的努力。无论如何,这两种方法都值得学习,并且对将来的项目很有用。
在http://www.picklingtools.com上有一个开源的c++库它允许您在c++中pickle对象(可能允许您重用您的从Python项目中pickle文件)。它最适合序列化标准Python数据结构(dict, list, tuples, int, float等),但可以工作与类一起工作(毕竟,Python类通常使用
一个简单的例子,展示了如何使用picklingtools库(并使其工作)(c++和Python)
#include "chooseser.h"
#include <iostream>
int main (int argc, char **argv)
{
// Create a Python style dictionary
Val v = Tab("{'a':1, 'b':2.2, 'c':'three', 'nested':{ 'zz':1 }");
v["d"] = "something";
// print out a nested key
cout << v["nested"]["zz"] << endl;
// Pickle the data structure to disk
DumpValToFile(v, "state.p0", SERIALIZE_P2);
// # Python side would read this same file with
// >>> import cPickle
// >>> result = cPickle.load( file('state.p0') ) # load fiigures out which prototcol
}
我可能会使用字典或列表来构建您的树:
questions_dict = { 'data': 'COW', 'left': None, 'right': { ''data':'CAT', left': None, 'right': None } }
print questions_dict['right']['data'] # Right child's data
LEFT = 1; RIGHT = 2; DATA = 0
questions_list = ["COW", None, ["CAT", None, None] ]
print questions_list[RIGHT][DATA] # Right child's data
有了它,你就可以在c++和Python之间来回切换字典或列表,做你需要做的事情。你可以按原样使用。
有关于如何在c++中pickle和反pickle的重要文档在文档选项卡下的网站。最好的起点可能是http://www.picklingtools.com/documentation与用户指南。
警告!危害吧!您可以使用c++的序列化来构建类(因此Python中的相同类将有一个c++的等效物),但这很重要;如果您可以留在内部,则更困难标准的Python数据结构,您的生活可以轻松得多。要做到这一点,你必须然后必须用构造函数注册一个c++类用这个系统。您必须有一个构建函数(见下面的一个简单示例):
// When registering things with the factory, they take in some tuple
// and return a Val: REDUCE tend to be more for built-in complicated
// types like Numeric, array and complex. BUILD tends to more for
// user-defined types.
typedef void (*FactoryFunction)(const Val& name,
const Val& input_tuple,
Val& environment,
Val& output_result);
// Example of how user-defined classes would probably serialize: the
// user-defined classes tend to be built with BUILD instead of REDUCE,
// which passes slightly different arguments to the tuple. As an
// example, magine a simple Python class:
//
// class Scott(object) :
// def __init__(self, n) : self.data = int(n)
//
// A dumps(a,2) (where a= Scott(100)) looks like
// 'x80x02c__main__nScottnqx01)x81qx02}qx03Ux04dataqx04Kdsb.'/
//
// type_object: a tuple (string_name, args). i.e., ('__main__nScottn', ())
// input: a dictionary i.e., {'data', 100 }
inline void BuildScottFactoryFunction (const Val& type_object,
const Val& input,
Val& /* environment */,
Val& output_result)
{
cout << "SCOTT:type_object:" << type_object << endl;
cout << "SCOTT:input:" << input << endl;
string name = type_object(0);
Tup& args = type_object(1);
cout << "name:" << name << " args:" << args << endl;
if (name!="__main__nScottn") throw runtime_error("Not right name");
Val& result = input("data");
output_result = result;
}
那么你必须在你自己的PickleLoader中注册这个类。
PickleLoader p(buffer, buffer_len);
p.registerFactory("__main__nScottn", BuildScottFactoryFunction);
你可以让它工作,这样你就可以让Python和c++类看起来和感觉一样,并使用pickle进行交流,但这比看起来要困难得多(部分原因是c++没有运行时自省的真正概念(它仅限于RTTI)),所以你倾向于用元组来描述你的整个c++类,字典,列表手动。然后用pickle加载器注册这些函数。这是可以做到的,但考虑到你的问题的简单性质,我还是坚持用Python数据结构(列表,字典,元组,整数,浮点数,字符串,None)然后用它们来代表你的20个问题树。
- 如何运行位于boost/libs/python/example/tutorial目录中的hello.cpp和Jamfil
- Pybind11:将元组列表从Python传递到C++
- 如何在c++中使用引用实现类似python的行为
- 是否可以通过C++扩展强制多个python进程共享同一内存
- 递归列出所有目录中的C++与Python与Ruby的性能
- IPC使用多个管道和分支进程来运行Python程序
- 从python中调用C++函数并获取返回值
- Python 3.7 和 excess_args 的 SWIG 问题
- Python中的for循环与C++有何不同
- 使用Pybind11向Python公开Eigen::张量
- Python str to C++ to Python str
- 如何使用Python从C++中读取谷物序列化数据
- 如何在C++中使用pybind11加载一个pickle python列表
- 如何在c++中使用system()来运行包含空格的python脚本
- python集合的C++等价物是什么.计数器
- 如果C++对象的类在另一个boost模块中声明,如何使用boost将指向该对象的指针返回到python
- 什么可以用来在 C++ 中保存图形等结构(Python pickle 等效物)
- 在boost python中pickle一个向量
- 提振.序列化和Boost.Python双向pickle
- c++数据存储取代Python pickle