可以使用 while(file >> ...) C++ 习语在 Cython 中读取文件吗?
Posted
技术标签:
【中文标题】可以使用 while(file >> ...) C++ 习语在 Cython 中读取文件吗?【英文标题】:Can one use the while(file >> ...) C++ idiom to read files in Cython? 【发布时间】:2019-12-30 11:03:41 【问题描述】:我想在 Cython 中使用 C++ 方式读取文件。
我有一个简单的文件阅读器,如下所示:
std::ifstream file(fileName);
while(file >> chromosome >> start >> end >> junk >> junk >> strand)
...
我可以在 Cython 中执行此操作吗?
【问题讨论】:
【参考方案1】:可能更好的选择是使用 python 解析功能(例如 pandas' 或 numpy's),或者,如果第一个解决方案不够灵活,则使用纯 C++ 对阅读器进行编码,然后从 Cython 调用该功能。
但是,您的方法也可以在 Cython 中使用,但为了使其发挥作用,需要跳过一些障碍:
-
整个
iostream
层次结构不是the provided libcpp-wrappers 的一部分,因此必须将其包装起来(如果不快速和脏,那就是几行)。
由于std::ifsteam
没有提供默认构造函数,我们无法在 Cython 中将其构造为具有自动生命周期的对象,需要注意内存管理。
另一个问题是包装使用定义的转换。文档中描述的不是很好(见这个SO-question),但是只支持operator bool()
]3,所以我们需要使用C++11(否则是operator void*() const;
)。
所以这是一个快速而简单的概念证明:
%%cython -+ -c=-std=c++11
cdef extern from "<fstream>" namespace "std" nogil:
cdef cppclass ifstream:
# constructor
ifstream (const char* filename)
# needed operator>> overloads:
ifstream& operator>> (int& val)
# others are
# ifstream& operator>> (unsigned int& val)
# ifstream& operator>> (long& val)
# ...
bint operator bool() # is needed,
# so while(file) can be evaluated
def read_with_cpp(filename):
cdef int a=0,b=0
cdef ifstream* foo = new ifstream(filename)
try:
while (foo[0] >> a >> b):
print(a, b)
finally: # don't forget to call destructor!
del foo
实际上operator>>(...)
的返回类型不是std::ifstream
而是std::basic_istream
- 我也懒得包装它。
现在:
>>> read_with_cpp(b"my_test_file.txt")
将文件内容打印到控制台。
但是,如上所述,我会用纯 C++ 编写解析并从 Cython 使用它(例如,通过传递函子,因此 cpp 代码可以使用 Python 功能),这是一个可能的实现:
%%cython -+
cdef extern from *:
"""
#include <fstream>
void read_file(const char* file_name, void(*line_callback)(int, int))
std::ifstream file(file_name);
int a,b;
while(file>>a>>b)
line_callback(a,b);
"""
ctypedef void(*line_callback_type)(int, int)
void read_file(const char* file_name, line_callback_type line_callback)
# use function pointer to get access to Python functionality in cpp-code:
cdef void line_callback(int a, int b):
print(a,b)
# expose functionality to pure Python:
def read_with_cpp2(filename):
read_file(filename, line_callback)
现在调用read_with_cpp2(b"my_test_file.txt")
会得到与上述相同的结果。
【讨论】:
整洁。我实际上有一个应用程序,其中 IO 是瓶颈,然后使用 C++ 读取文件比 Cython 的for line in f_handle; line.split()...
更快。期待对您的功能进行基准测试。此外,在 Cython 中从未见过 cdef extern from *
。您有文档的简短链接或解释吗?
@TheUnfunCat 见cython.readthedocs.io/en/latest/src/userguide/…
@TheUnfunCat 我不认为 C++ IO 通常很快。如果您担心速度,可能值得尝试 C IO(因为它不涉及类或运算符重载,所以包装起来更简单)以上是关于可以使用 while(file >> ...) C++ 习语在 Cython 中读取文件吗?的主要内容,如果未能解决你的问题,请参考以下文章
while ( input >> s ) input是类ifstream的一个实例,这种写法对吗?求解析。
java 罕见的依赖报错 jstat: error while loading shared libraries: libjli.so: cannot open shared object file