Python調(diào)用C/C++函數(shù)庫的多種方法與實(shí)踐指南
引言
Python作為一門高級(jí)編程語言,以其簡(jiǎn)潔的語法和豐富的庫生態(tài)贏得了開發(fā)者的青睞。然而,在計(jì)算密集型任務(wù)中,Python的性能往往無法滿足要求。Python調(diào)用C/C++函數(shù)庫成為提升應(yīng)用性能的關(guān)鍵技術(shù)路徑,通過將底層計(jì)算邏輯用C/C++實(shí)現(xiàn),再通過適當(dāng)?shù)慕涌谂cPython交互,可以在保持開發(fā)效率的同時(shí)獲得接近系統(tǒng)語言的執(zhí)行性能。本文將深入探討Python調(diào)用C/C++函數(shù)庫的多種方法,包括它們的工作原理、實(shí)現(xiàn)步驟、優(yōu)缺點(diǎn)及適用場(chǎng)景,幫助開發(fā)者根據(jù)具體需求選擇最適合的集成方案。
一、主流調(diào)用方法及其基本原理
Python調(diào)用C/C++函數(shù)庫主要有五種主流方法,各有其獨(dú)特的實(shí)現(xiàn)機(jī)制和適用范圍:
ctypes是Python標(biāo)準(zhǔn)庫的一部分,提供了一種直接與C語言兼容的數(shù)據(jù)類型和函數(shù)調(diào)用方式。它通過動(dòng)態(tài)加載共享庫(.so或.dll)并在內(nèi)存中創(chuàng)建對(duì)應(yīng)的函數(shù)指針來實(shí)現(xiàn)調(diào)用,無需任何預(yù)編譯步驟。ctypes的工作原理類似于Windows平臺(tái)上的DLL調(diào)用或Linux平臺(tái)上的動(dòng)態(tài)鏈接庫加載,通過函數(shù)指針和參數(shù)類型轉(zhuǎn)換直接調(diào)用C函數(shù)。
SWIG(SimplifiedWrapper and Interface Generator)是一個(gè)開源的軟件接口生成器,能夠自動(dòng)生成C/C++與Python之間的接口代碼。SWIG通過解析C/C++頭文件和接口描述文件(.i),生成特定語言的包裝代碼,這些代碼負(fù)責(zé)在Python和C/C++之間進(jìn)行參數(shù)轉(zhuǎn)換和內(nèi)存管理。SWIG支持多種語言和復(fù)雜的C++特性,如類、繼承、模板等,是處理大型C++項(xiàng)目時(shí)的常用工具。
cffi(C Foreign Function Interface)是另一個(gè)Python庫,用于調(diào)用C語言函數(shù)。與ctypes不同,cffi采用聲明式接口,開發(fā)者可以使用接近C語法的聲明來定義函數(shù)和數(shù)據(jù)結(jié)構(gòu)。cffi的優(yōu)勢(shì)在于其可讀性和維護(hù)性,同時(shí)它還支持與PyPy解釋器的兼容,這在某些高性能場(chǎng)景中非常有價(jià)值。
Python/C API是Python官方提供的擴(kuò)展接口,允許開發(fā)者用C/C++編寫Python模塊。這種方法需要開發(fā)者深入理解Python對(duì)象模型和內(nèi)存管理機(jī)制,通過一系列宏和函數(shù)(如PyMOD初始化、PyMethodDef定義等)手動(dòng)創(chuàng)建Python可調(diào)用的對(duì)象和方法。Python/C API提供了最大的靈活性,但開發(fā)復(fù)雜度也最高。
pybind11是一個(gè)現(xiàn)代的C++庫,旨在簡(jiǎn)化C++與Python之間的綁定過程。它通過C++模板和編譯時(shí)類型推導(dǎo),將C++代碼無縫暴露給Python,無需手動(dòng)編寫大量包裝代碼。pybind11支持C++11及更高版本的特性,如智能指針、移動(dòng)語義等,是當(dāng)前推薦的C++與Python集成方案。
二、實(shí)現(xiàn)步驟與代碼示例
1. ctypes方法
ctypes是最簡(jiǎn)單的調(diào)用方式,適合快速原型開發(fā)和簡(jiǎn)單函數(shù)調(diào)用。實(shí)現(xiàn)步驟如下:
編寫C/C++函數(shù)并導(dǎo)出為共享庫:
// add.c
#include <stdio.h>
int add_int(int a, int b) {
printf("Adding %d and %d\n", a, b);
return a + b;
}
float add_float(float a, float b) {
printf("Adding %f and %f\n", a, b);
return a + b;
}編譯為共享庫:
gcc -shared -Wl,-soname,adder -o adder.so -fPIC add.c
Python調(diào)用代碼:
import ctypes
# 加載共享庫
adder = ctypes.CDLL('./adder.so')
# 設(shè)置函數(shù)參數(shù)類型和返回值類型
adder.add_int.argtypes = [ctypes.c_int, ctypes.c_int]
adder.add_int.restype = ctypes.c_int
adder.add_float.argtypes = [ctypes.c_float, ctypes.c_float]
adder.add_float支柱 = ctypes.c_float
# 調(diào)用函數(shù)
result_int = adder.add_int(4, 5)
print(f"4 + 5 = {result_int}")
a = ctypes.c_float(5.5)
b = ctypes.c_float(4.1)
result_float = adder.add_float(a, b)
print(f"5.5 + 4.1 = {result_float}")C++類調(diào)用:由于C++支持函數(shù)重載,編譯器會(huì)修改函數(shù)名,ctypes無法直接調(diào)用。解決方法是在C++代碼中使用extern “C”聲明:
// TestLib.cpp
#include <iostream>
extern "C" {
class TestLib {
public:
void display() {
std::cout << "First display" << std::endl;
}
void display(int a) {
std::cout << "Second display:" << a << std::endl;
}
};
TestLib global_obj;
void display() {
global_obj.display();
}
void display_int(int a) {
global_obj.display(a);
}
}編譯命令:
g++ -shared -fPIC TestLib.cpp -o libTestLib.so
Python調(diào)用:
import ctypes
lib = ctypes.CDLL('./libTestLib.so')
lib.display()
lib.display_int(100)2. cffi方法
cffi提供了更接近C語法的接口定義,適合需要在Python中嵌入C代碼的場(chǎng)景。實(shí)現(xiàn)步驟如下:
編寫C/C++函數(shù)并導(dǎo)出為共享庫:
// ffi_test.cpp
extern "C" {
int add(int a, int b) {
return a + b;
}
}編譯命令:
g++ffi_test.cpp -fPIC -shared -o libffi_test.so
Python調(diào)用代碼:
from cffi import FFI
ffi = FFI()
# 聲明C函數(shù)接口
ffi.cdef(
"""int add(int a, int b);"""
)
# 加載共享庫
lib = ffi.dlopen('libffi_test.so')
# 調(diào)用函數(shù)
print(f"3 + 4 = {lib.add(3, 4)}")Python代碼中嵌入C代碼(無需編譯為共享庫):
from cffi import FFI
ffi = FFI()
# 聲明C函數(shù)接口
ffi.cdef(
"""int add(int a, int b);"""
)
# 定義并編譯C代碼
lib =ffi.verify(
"""
int add(int a, int b) {
return a + b;
}
"""
)
print(f"3 + 4 = {lib.add(3, 4)}")3. SWIG方法
SWIG適合處理復(fù)雜的C++項(xiàng)目,能夠自動(dòng)處理類、繼承、模板等特性。實(shí)現(xiàn)步驟如下:
編寫C++類和接口文件:
// TestLib.h
#include <iostream>
class TestLib {
public:
TestLib();
~TestLib();
void display();
void display(int a);
int add(int a, int b);
float add(float a, float b);
};
// TestLib.cpp
#include "TestLib.h"
TestLib::TestLib() {
std::cout << "TestLib created" << std::endl;
}
TestLib::~TestLib() {
std::cout << "TestLib destroyed" << std::endl;
}
void TestLib::display() {
std::cout << "First display" << std::endl;
}
void TestLib::display(int a) {
std::cout << "Second display:" << a << std::endl;
}
int TestLib::add(int a, int b) {
return a + b;
}
float TestLib::add(float a, float b) {
return a + b;
}
// TestLib.i
%module TestLib
%{
#include "TestLib.h"
%}
// 聲明C++類
class TestLib {
public:
TestLib();
~TestLib();
void display();
void display(int a);
int add(int a, int b);
float add(float a, float b);
};編譯SWIG接口:
swig -c++ -python TestLib.i g++ -fPIC -c TestLib.cpp g++ -fPIC -c TestLib wrap.cpp g++ -shared TestLib.o TestLib wrap.o -o _TestLib.so
Python調(diào)用代碼:
import TestLib
# 創(chuàng)建C++對(duì)象
obj = TestLib.TestLib()
# 調(diào)用成員函數(shù)
obj.display()
obj.display(100)
# 調(diào)用重載函數(shù)
print(f"5 + 3 = {obj.add(5, 3)}")
print(f"2.5 + 3.1 = {obj.add(2.5, 3.1)}")4. Python/C API方法
Python/C API提供了最大的靈活性,但開發(fā)復(fù)雜度也最高。實(shí)現(xiàn)步驟如下:
編寫C++擴(kuò)展模塊:
// module.cpp
#include <Python.h>
#include <iostream>
// C++類
class TestLib {
public:
void display() {
std::cout << "First display" << std::endl;
}
void display(int a) {
std::cout << "Second display:" << a << std::endl;
}
int add(int a, int b) {
return a + b;
}
float add(float a, float b) {
return a + b;
}
};
// Python類型定義
static PyTypeObject TestLibType = {
PyVarObjectHead_init
"TestLib",
sizeof(TestLib),
0,
// 方法表
.tpMethods = methods,
};
// 方法定義
static PyMethodDef methods[] = {
{"display", (PyCFunction)display, METH_VARARGS, "Display message"},
{"display_int", (PyCFunction)display_int, METH_VARARGS, "Display integer"},
{"add", (PyCFunction)add, METH_VARARGS, "Add two numbers"},
{NULL, NULL, 0, NULL}
};
// 模塊初始化函數(shù)
static struct PyModuleDef moduledef = {
PyModuleDefHead_init
"module",
NULL,
0,
.mMethods = NULL,
.mModuleInit = PyMODInit_module
};
PyMODInit_t PyMODInit_module() {
// 初始化Python解釋器
Py_Initialize();
// 創(chuàng)建模塊
PythonModule* module = PyModuleDefInit(&moduledef);
// 創(chuàng)建類型
if (PyType_Ready(&TestLibType) < 0)
return NULL;
// 將類型添加到模塊
PyModuleDictSetItemStr(module-> ob_type, "TestLib", (PyObject*) &TestLibType);
return module;
}編寫setup.py:
from setuptools import setup, Extension
module = Extension('module',
sources=['module.cpp'])
setup(name='module',
version='1.0',
description='Python C++ extension',
ext_modules=[module])編譯擴(kuò)展模塊:
python setup.py build_ext --inplace
Python調(diào)用代碼:
import module
# 創(chuàng)建C++對(duì)象
obj = module.TestLib()
# 調(diào)用成員函數(shù)
obj.display()
obj.display_int(100)
# 調(diào)用函數(shù)
print(f"5 + 3 = {obj.add(5, 3)}")
print(f"2.5 + 3.1 = {obj.add(2.5, 3.1)}")5. pybind11方法
pybind11是目前推薦的現(xiàn)代C++與Python集成方案,實(shí)現(xiàn)步驟如下:
編寫C++代碼和綁定:
// example.cpp
#include <pybind11/pybind11.h>
using namespace pybind11;
class TestLib {
public:
void display() {
std::cout << "First display" << std::endl;
}
void display(int a) {
std::cout << "Second display:" << a << std::endl;
}
int add(int a, int b) {
return a + b;
}
float add(float a, float b) {
return a + b;
}
};
PYBIND11_MODULE(example, m) {
// 綁定C++類到Python
m.def("add_int", &TestLib::add, "Add two integers");
m.def("add_float", &TestLib::add, "Add two floats");
// 綁定類到Python
py::class_<TestLib>(m, "TestLib")
.def py::init<>())
.def("display", &TestLib::display)
.def("display_int", &TestLib::display_int);
}編譯擴(kuò)展模塊:
c++ -O3 -Wall -shared -std=c++11 -fPIC $(python3 -m pybind11 --includes) example.cpp -o example$(python3-config --extension-suffix)
Python調(diào)用代碼:
import example
# 創(chuàng)建C++對(duì)象
obj = example.TestLib()
# 調(diào)用成員函數(shù)
obj.display()
obj.display_int(100)
# 調(diào)用函數(shù)
print(f"5 + 3 = {example.add_int(5, 3)}")
print(f"2.5 + 3.1 = {example.add_float(2.5, 3.1)}")三、不同方法的優(yōu)缺點(diǎn)與適用場(chǎng)景
下表對(duì)五種主流方法進(jìn)行了系統(tǒng)性比較:
| 方法 | 開發(fā)復(fù)雜度 | 性能 | 語言支持 | 維護(hù)性 | 適用場(chǎng)景 |
| ctypes | 低 | 中 | C函數(shù) | 低 | 快速原型開發(fā)、簡(jiǎn)單函數(shù)調(diào)用 |
| cffi | 中 | 高 | C函數(shù) | 中 | 需要PyPy兼容、輕量級(jí)C調(diào)用 |
| SWIG | 中高 | 高 | C++類、繼承、模板 | 中 | 大型C++項(xiàng)目、復(fù)雜接口 |
| Python/C API | 高 | 最高 | C++類、繼承、模板 | 低 | 需要深度定制、高性能需求 |
| pybind11 | 中 | 高 | C++11及以上 | 高 | 現(xiàn)代C++項(xiàng)目、簡(jiǎn)潔接口 |
ctypes的優(yōu)勢(shì)在于簡(jiǎn)單易用,無需額外編譯步驟,適合快速驗(yàn)證C函數(shù)調(diào)用。但其缺點(diǎn)也很明顯:不支持C++類和重載,需要手動(dòng)處理參數(shù)類型和內(nèi)存管理,難以處理復(fù)雜數(shù)據(jù)結(jié)構(gòu)。
cffi相比ctypes提供了更好的可讀性和維護(hù)性,支持更接近C語法的聲明方式,同時(shí)兼容PyPy解釋器。這對(duì)于需要在不同Python實(shí)現(xiàn)上運(yùn)行的程序非常有價(jià)值。然而,cffi同樣不支持C++類和重載,需要通過C接口間接調(diào)用C++功能。
SWIG是處理復(fù)雜C++項(xiàng)目的強(qiáng)大工具,能夠自動(dòng)生成Python綁定代碼,支持類、繼承、模板等高級(jí)特性。SWIG的靈活性使其成為許多大型項(xiàng)目的首選。然而,SWIG的學(xué)習(xí)曲線較陡,需要編寫接口描述文件,并且對(duì)于某些C++語法(如非常規(guī)類型聲明)的支持有限。
Python/C API提供了最大的靈活性和控制權(quán),允許開發(fā)者完全定制Python與C/C++之間的交互。這對(duì)于需要深度集成或特殊性能優(yōu)化的場(chǎng)景非常有價(jià)值。然而,Python/C API的開發(fā)復(fù)雜度最高,需要深入理解Python對(duì)象模型和內(nèi)存管理機(jī)制,維護(hù)成本也相應(yīng)較高。
pybind11是目前推薦的現(xiàn)代C++與Python集成方案,它結(jié)合了SWIG的靈活性和Python/C API的性能優(yōu)勢(shì),同時(shí)簡(jiǎn)化了開發(fā)流程。pybind11支持C++11及以上版本的特性,如智能指針、移動(dòng)語義等,使得C++代碼可以保持現(xiàn)代風(fēng)格。此外,pybind11還提供了豐富的文檔和示例,降低了學(xué)習(xí)曲線。然而,pybind11需要C++11及以上版本的編譯器支持,這對(duì)于某些遺留系統(tǒng)可能構(gòu)成限制。
四、性能比較與選擇建議
在實(shí)際應(yīng)用中,性能是選擇調(diào)用方法的重要考量因素。根據(jù)多個(gè)測(cè)試案例,不同方法的性能表現(xiàn)如下:
ctypes的調(diào)用開銷約為純C函數(shù)的1.5-2倍,適合簡(jiǎn)單的函數(shù)調(diào)用和快速原型開發(fā)。對(duì)于需要頻繁調(diào)用的函數(shù),ctypes的性能可能無法滿足要求。
cffi在性能上與ctypes相當(dāng),但在代碼可讀性和維護(hù)性方面有所優(yōu)勢(shì)。此外,cffi在PyPy解釋器上的表現(xiàn)通常優(yōu)于ctypes,這對(duì)于需要高性能且與PyPy兼容的場(chǎng)景非常有價(jià)值。
SWIG生成的綁定代碼在性能上接近原生C/C++調(diào)用,但需要額外的編譯步驟。對(duì)于復(fù)雜的C++項(xiàng)目,SWIG的性能開銷通常可以忽略不計(jì)。
Python/C API提供了最高的性能,幾乎與純C/C++調(diào)用相當(dāng),適合對(duì)性能要求極高的場(chǎng)景。然而,其開發(fā)復(fù)雜度也最高,需要開發(fā)者深入理解Python內(nèi)部機(jī)制。
pybind11在性能上與Python/C API相當(dāng),但開發(fā)復(fù)雜度顯著降低。這對(duì)于大多數(shù)現(xiàn)代C++項(xiàng)目來說是一個(gè)理想的選擇,可以在保持高性能的同時(shí)減少開發(fā)和維護(hù)成本。
基于上述分析,以下是針對(duì)不同場(chǎng)景的調(diào)用方法選擇建議:
對(duì)于簡(jiǎn)單函數(shù)調(diào)用和快速原型開發(fā),ctypes是最佳選擇,其簡(jiǎn)單易用的特性可以快速驗(yàn)證C函數(shù)調(diào)用。
對(duì)于需要PyPy兼容或輕量級(jí)C調(diào)用的場(chǎng)景,cffi是一個(gè)更好的選擇,它提供了更好的可讀性和維護(hù)性。
對(duì)于大型C++項(xiàng)目或復(fù)雜接口,SWIG是首選工具,它能夠自動(dòng)生成Python綁定代碼,支持類、繼承、模板等高級(jí)特性。
對(duì)于需要深度定制或特殊性能優(yōu)化的場(chǎng)景,Python/C API提供了最大的靈活性,但需要開發(fā)者具備深入的Python和C/C++知識(shí)。
對(duì)于現(xiàn)代C++項(xiàng)目,pybind11是當(dāng)前推薦的方案,它結(jié)合了SWIG的靈活性和Python/C API的性能優(yōu)勢(shì),同時(shí)簡(jiǎn)化了開發(fā)流程,支持C++11及以上版本的特性。
五、實(shí)際應(yīng)用案例與最佳實(shí)踐
科學(xué)計(jì)算與數(shù)據(jù)分析:在RPLIDAR數(shù)據(jù)通訊和解析項(xiàng)目中,使用C++編寫數(shù)據(jù)解析模塊,將運(yùn)算結(jié)果寫入共享內(nèi)存塊,再通過Python進(jìn)行數(shù)據(jù)處理和可視化。這種方法將C++的高性能與Python的易用性相結(jié)合,顯著提升了程序的執(zhí)行效率。
機(jī)器學(xué)習(xí)與深度學(xué)習(xí):在CGAL(計(jì)算幾何算法庫)的Python綁定中,使用SWIG自動(dòng)生成Python接口,同時(shí)保留C++的模板特性和高性能。這種方法使得復(fù)雜的幾何計(jì)算可以在Python環(huán)境中高效執(zhí)行,同時(shí)保持代碼的可維護(hù)性和擴(kuò)展性。
Web開發(fā)與系統(tǒng)集成:在Flask框架下集成模擬 機(jī)接口(如RINSIM平臺(tái)的Dataport.dll),使用pybind11對(duì)C++函數(shù)進(jìn)行封裝,生成Python模塊。這種方法使得復(fù)雜的工業(yè)控制邏輯可以在Python Web應(yīng)用中高效調(diào)用,同時(shí)保持代碼的簡(jiǎn)潔性和可讀性。
最佳實(shí)踐:
- 明確需求:在選擇調(diào)用方法之前,明確項(xiàng)目的具體需求,包括性能要求、復(fù)雜度、維護(hù)周期等。
- 簡(jiǎn)化接口:無論使用哪種方法,都應(yīng)盡量簡(jiǎn)化C/C++與Python之間的接口,減少跨語言調(diào)用的開銷。
- 處理內(nèi)存管理:跨語言調(diào)用需要特別注意內(nèi)存管理,避免內(nèi)存泄漏或無效指針訪問。
- 利用現(xiàn)代C++特性:在使用pybind11等現(xiàn)代工具時(shí),充分利用C++11及以上版本的特性,如智能指針、移動(dòng)語義等,簡(jiǎn)化代碼并提高安全性。
- 測(cè)試與驗(yàn)證:在實(shí)際應(yīng)用中,充分測(cè)試跨語言調(diào)用的性能和穩(wěn)定性,確保接口的正確性和可靠性。
六、未來發(fā)展趨勢(shì)與技術(shù)展望
隨著Python和C++生態(tài)的不斷發(fā)展,Python調(diào)用C/C++函數(shù)庫的技術(shù)也在持續(xù)演進(jìn):
類型系統(tǒng)增強(qiáng):現(xiàn)代工具如pybind11和SWIG正在不斷改進(jìn)對(duì)C++類型系統(tǒng)的支持,使得C++的復(fù)雜數(shù)據(jù)結(jié)構(gòu)可以在Python中更自然地表示和操作。
編譯器支持改進(jìn):C++編譯器(如GCC、Clang)對(duì)Python綁定的支持也在不斷提升,使得C++代碼與Python的集成更加無縫。
多解釋器兼容:隨著PyPy等替代Python解釋器的普及,cffi等工具對(duì)多解釋器的兼容性變得越來越重要,未來可能會(huì)有更多工具支持這一特性。
自動(dòng)化綁定生成:隨著AI技術(shù)的發(fā)展,可能會(huì)出現(xiàn)更智能的綁定生成工具,能夠自動(dòng)分析C/C++代碼并生成Python接口,進(jìn)一步降低開發(fā)復(fù)雜度。
跨平臺(tái)支持:Python應(yīng)用通常需要跨平臺(tái)運(yùn)行,未來工具可能會(huì)更好地支持Windows、Linux、macOS等不同平臺(tái)的C/C++庫調(diào)用。
性能優(yōu)化:隨著計(jì)算需求的不斷提升,工具可能會(huì)提供更精細(xì)的性能優(yōu)化選項(xiàng),如緩存機(jī)制、并行計(jì)算支持等。
結(jié)論:Python調(diào)用C/C++函數(shù)庫是提升應(yīng)用性能的重要技術(shù)路徑。根據(jù)項(xiàng)目需求、開發(fā)復(fù)雜度、性能要求和維護(hù)周期等因素,可以選擇合適的調(diào)用方法。對(duì)于大多數(shù)現(xiàn)代C++項(xiàng)目,pybind11是當(dāng)前推薦的方案,它結(jié)合了SWIG的靈活性和Python/C API的性能優(yōu)勢(shì),同時(shí)簡(jiǎn)化了開發(fā)流程。而對(duì)于簡(jiǎn)單的函數(shù)調(diào)用和快速原型開發(fā),ctypes或cffi可能是更好的選擇。無論選擇哪種方法,都應(yīng)遵循最佳實(shí)踐,確保接口的正確性和可靠性,同時(shí)充分利用現(xiàn)代C++和Python特性,提升代碼質(zhì)量和性能。
以上就是Python調(diào)用C/C++函數(shù)庫的多種方法與實(shí)踐指南的詳細(xì)內(nèi)容,更多關(guān)于Python調(diào)用C/C++函數(shù)庫的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python使用自帶的ConfigParser模塊讀寫ini配置文件
這篇文章主要介紹了Python使用自帶的ConfigParser模塊讀寫ini配置文件的方法,ConfigParser中包含了對(duì)ini的節(jié)section的一些基本操作,使得改寫ini時(shí)非常簡(jiǎn)便,需要的朋友可以參考下2016-06-06
pycharm 將django中多個(gè)app放到同個(gè)文件夾apps的處理方法
今天小編就為大家分享一篇pycharm 將django中多個(gè)app放到同個(gè)文件夾apps的處理方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-05-05
使用Django啟動(dòng)命令行及執(zhí)行腳本的方法
今天小編就為大家分享一篇使用Django啟動(dòng)命令行及執(zhí)行腳本的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-05-05
python PIL/cv2/base64相互轉(zhuǎn)換實(shí)例
今天小編就為大家分享一篇python PIL/cv2/base64相互轉(zhuǎn)換實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-01-01
python庫Celery異步發(fā)送電子郵件定時(shí)生成報(bào)告實(shí)戰(zhàn)示例
這篇文章主要介紹了python庫Celery異步發(fā)送電子郵件定時(shí)生成報(bào)告實(shí)戰(zhàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01
利用python實(shí)現(xiàn)對(duì)excel文件進(jìn)行加密
由于文件內(nèi)容的私密性,需要對(duì)Excel文件進(jìn)行加密,保護(hù)文件以免給第三方看到,本文將以Python語言為例,和大家講講如何對(duì)Excel文件進(jìn)行加密,感興趣的小伙伴可以了解下2025-04-04
pandas重置索引標(biāo)簽的實(shí)現(xiàn)示例
在使用Pandas進(jìn)行數(shù)據(jù)處理時(shí),有時(shí)候我們可能會(huì)需要對(duì)數(shù)據(jù)進(jìn)行重置索引的操作,本文主要介紹了pandas重置索引標(biāo)簽的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下2024-04-04
基于Python進(jìn)行定時(shí)任務(wù)管理封裝
這篇文章主要為大家詳細(xì)介紹了如何基于Python進(jìn)行定時(shí)任務(wù)管理封裝,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以參考下2024-12-12
數(shù)據(jù)驅(qū)動(dòng)測(cè)試DDT之Selenium讀取Excel文件
這篇文章主要為大家介紹了數(shù)據(jù)驅(qū)動(dòng)測(cè)試DDT之Selenium讀取Excel文件,2021-11-11
keras 兩種訓(xùn)練模型方式詳解fit和fit_generator(節(jié)省內(nèi)存)
這篇文章主要介紹了keras 兩種訓(xùn)練模型方式詳解fit和fit_generator(節(jié)省內(nèi)存),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-07-07

