import xxx
,默认情况下python解释器会搜索当前目录、已安装的内置模块和第三方模块。临时添加路径
sys.path 返回的是一个列表,该路径已经添加到系统的环境变量了
当我们要添加自己的搜索目录时,可以通过列表的append()方法; sys.path.append()
对于模块和自己写的脚本不在同一个目录下,在脚本开头加 sys.path.append('xxx')
例如:
导入的 xxx
包在另一个项目文件中,在自己写的程序中需要用到该包时,首先加载导入的 xxx
包,加载的时候 python解释器会去 sys.path
默认搜索路径去搜索。
如果通过 sys.path
中的路径可以搜索到 xxx
包,然后加载。如果无法通过sys.path
中的路径搜索到xxx
包,即说明自己的程序中引用的xxx
包与自己程序脚本所在目录不在同一个路径。就需要将 xxx
包的搜索路径添加到自己程序脚本的默认搜索路径中,重新运行自己的程序脚本。
注意:
这种方法是运行时修改,脚本运行后就会失效。
sys.path.append('..')
括号里这两个点是 上一级目录的意思,还可以 sys.path.append('../..')
永久添加路径
把路径添加到系统的环境变量,或把该路径的文件夹放进已经添加到系统环境变量的路径内。环境变量的内容会自动添加到模块搜索路径中。
永久添加路径到sys.path中,方式有三
将写好的py文件放到 已经添加到系统环境变量的 目录下
在 /usr/lib/python2.7/site-packages
下面新建一个.pth
文件(以pth
作为后缀名) ,将模块的路径写进去,一行一个路径
使用PYTHONPATH
环境变量 export PYTHONPATH=$PYTHONPATH:/home/liu/shell/config
append
导入案例:
// 使用python之前,要调用Py_Initialize();这个函数进行初始化
Py_Initialize();
// 判断初始化是否成功
if(!Py_IsInitialized()) {
LOG(ERROR)<<"python init failed !";
return ;
}
// 添加python文件所在的位置
std::string python_path = std::string(common::kSourceDirectory) + "/hybrid_slam/tmp/";
PyRun_SimpleString("import sys"); // 导入sys库
std::string cmd_path = "sys.path.append(\"" + python_path + "\")";
LOG(INFO)<<"path: "<<cmd_path;
PyRun_SimpleString(cmd_path.c_str()); // 添加环境变换
第零步 初始化,并 导入python文件位置
Py_Initialize();
第一步是 导入.py文件:
PyObject* pModule
来存储导入的 .py
文件模块, 调用的方法是 PyImport_ImportModule(path):
PyObject* pModule = PyImport_ImportModule("test_py");
PyObject* pDict
来存储导入模块中的方法字典, 调用的方法是 PyModule_GetDict(module):
PyObject* pDict = PyModule_GetDict(pModule);
第二步是导入已导入模块中的方法或类:
2.1、 获取方法, 调用的方法是 PyDict_GetItemString(dict, methodName):
Eg: PyObject* pFunHi = PyDict_GetItemString(pDict, "sayhi");
**2.2、**获取类,调用的方法同上, 注意后面的字符串对应于.py
文件中的类/方法名:
Eg: PyObject* pClassSecond = PyDict_GetItemString(pDict, "Second");
上面两步中获取字典可以不需要,直接基于名字得到对象 PyObject_GetAttrString(module, "TestPrint")
Eg: pFunc = PyObject_GetAttrString(pModule, "TestPrint"); //这里是要调用的函数名
第三步是使用导入的方法或类
PyObject_CallFunction(pFunc, "s", args)
即可:PyInstance_New(pClass, NULL, NULL)
即可:PyObject* pInstanceSecond = PyInstance_New(pClassSecond, NULL, NULL);
PyObject *pConstruct = PyInstanceMethod_New(pClassPerson); ``//python3
pClassSecond
为第二步.2中获取的类指针PyObject_CallMethod(pInstance, methodname, "O", args)
即可:PyObject_CallMethod(pInstanceSecond, "invoke", "O", pInstancePerson);
第四步销毁这些对象: Py_DECREF(pointer);
第五步关闭,与第一步打开对应: Py_Finalize();
/* Py_BuildValue 它识别一组类似于 PyArg_ParseTuple() 识别的格式单元,但参数(是函数的输入,而不是输出)不能是指针,只是值。
* 它返回一个新的 Python 对象,适合从 Python 调用的 C 函数返回。
类型对应:
s:string=char*,
s#:string_sub,
z:s,
z#:s#,
i:int,
b:i,
h:short int,
l:long int,
c:char,
d:double,
f:float,
o:pyobject
转换函数:
Py_BuildValue("") None
Py_BuildValue("i", 123) 123
Py_BuildValue("iii", 123, 456, 789) (123, 456, 789)
Py_BuildValue("s", "hello") 'hello'
Py_BuildValue("ss", "hello", "world") ('hello', 'world')
Py_BuildValue("s#", "hello", 4) 'hell'
Py_BuildValue("()") ()
Py_BuildValue("(i)", 123) (123,)
Py_BuildValue("(ii)", 123, 456) (123, 456)
Py_BuildValue("(i,i)", 123, 456) (123, 456)
Py_BuildValue("[i,i]", 123, 456) [123, 456]
Py_BuildValue("{s:i,s:i}",
"abc", 123, "def", 456) {'abc': 123, 'def': 456}
Py_BuildValue("((ii)(ii)) (ii)",
1, 2, 3, 4, 5, 6) (((1, 2), (3, 4)), (5, 6))
*/
/**
int ok;
int i, j;
long k, l;
const char *s;
int size;
ok = PyArg_ParseTuple(args, "lls", &k, &l, &s); // Two longs and a string
// Possible Python call: f(1, 2, 'three')
ok = PyArg_ParseTuple(args, "s", &s); // A string
// Possible Python call: f('whoops!')
ok = PyArg_ParseTuple(args, "lls", &k, &l, &s); // Two longs and a string
// Possible Python call: f(1, 2, 'three')
ok = PyArg_ParseTuple(args, "(ii)s#", &i, &j, &s, &size);
// A pair of ints and a string, whose size is also returned
// Possible Python call: f((1, 2), 'three')
{
const char *file;
const char *mode = "r";
int bufsize = 0;
ok = PyArg_ParseTuple(args, "s|si", &file, &mode, &bufsize);
// A string, and optionally another string and an integer
// Possible Python calls:
// f('spam')
// f('spam', 'w')
// f('spam', 'wb', 100000)
}
{
int left, top, right, bottom, h, v;
ok = PyArg_ParseTuple(args, "((ii)(ii))(ii)",
&left, &top, &right, &bottom, &h, &v);
// A rectangle and a point
// Possible Python call:
// f(((0, 0), (400, 300)), (10, 10))
}
{
Py_complex c;
ok = PyArg_ParseTuple(args, "D:myfunction", &c);
// a complex, also providing a function name for errors
// Possible Python call: myfunction(1+2j)
}
**/
测试一个打印 和 一个相加,其中相加返回一个整数
// 测试 HelloWorld
pFunc = PyObject_GetAttrString(pModule, "TestPrint"); //这里是要调用的函数名
PyEval_CallObject(pFunc, NULL); //调用函数,NULL表示参数为空
// 测试 Add,传两个int型参数
pFunc = PyObject_GetAttrString(pModule, "TestAdd"); //Add:Python文件中的函数名
{
//创建参数:
PyObject *pArgs = PyTuple_New(2); //函数调用的参数传递均是以元组的形式打包的,2表示参数个数
PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", 5)); //0---序号 i表示创建int型变量
PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", 7)); //1---序号
//返回值
PyObject *pReturn = NULL;
pReturn = PyEval_CallObject(pFunc, pArgs); //调用函数
if(pReturn) {
//将返回值转换为int类型
int result;
if(PyArg_Parse(pReturn, "i", &result)) { //i表示转换成int型变量
LOG(INFO)<<"5+7 = "<<result;
ASSERT_EQ(result,12);
} else {
LOG(ERROR)<<"TestAdd return trans int error";
}
} else {
LOG(ERROR)<<"TestAdd return nullptr";
}
}
python 端:
def prRed(skk): print("\033[91m {}\033[00m" .format(skk))
def prBlue(skk): print("\033[94m {}\033[00m" .format(skk))
def TestPrint() :
prRed("hello world print_test!")
def TestAdd(a,b) :
return a+b
测试 一个二维位姿取逆
// 测试 2d 位姿取逆
pFunc = PyObject_GetAttrString(pModule, "Pose2dInverse1"); //Add:Python文件中的函数名
{
PyObject *pArgs = PyTuple_New(3);
PyTuple_SetItem(pArgs, 0, Py_BuildValue("d", 1.));
PyTuple_SetItem(pArgs, 1, Py_BuildValue("d", 2.));
PyTuple_SetItem(pArgs, 2, Py_BuildValue("d", 30./180*3.1415926));
//返回值
PyObject *pReturn = NULL;
pReturn = PyEval_CallObject(pFunc, pArgs); //调用函数
if(pReturn) {
LOG(INFO)<<"Pose2dInverse1 have result";
//将返回值转换为int类型
const char* result;
if(PyArg_Parse(pReturn, "s", &result)) {
std::string sss(result);
LOG(INFO)<<"Pose2dInverse1 : "<<sss;
} else {
LOG(ERROR)<<"Pose2dInverse1 trans double3 error";
}
} else {
LOG(ERROR)<<"Pose2dInverse1 return nullptr";
}
}
// 测试 2d 位姿取逆
pFunc = PyObject_GetAttrString(pModule, "Pose2dInverse"); //Add:Python文件中的函数名
{
PyObject *pArgs = PyTuple_New(3);
PyTuple_SetItem(pArgs, 0, Py_BuildValue("d", 1.));
PyTuple_SetItem(pArgs, 1, Py_BuildValue("d", 2.));
PyTuple_SetItem(pArgs, 2, Py_BuildValue("d", 30./180*3.1415926));
//返回值
PyObject *pReturn = NULL;
pReturn = PyEval_CallObject(pFunc, pArgs); //调用函数
if(pReturn) {
//将返回值转换为int类型
double result[3];
if(PyArg_ParseTuple(pReturn, "ddd", &result[0],&result[1],&result[2])) {
LOG(INFO)<<"0result: "<<result[0]<<" "<<result[1]<<" "<<result[2];
} else {
LOG(ERROR)<<"Pose2dInverse trans double3 error";
}
} else {
LOG(ERROR)<<"Pose2dInverse return nullptr";
}
}
python 代码:
def Pose2dInverse(x,y,yaw) :
"""
2d pose 取 返
in: x y yaw ; out: x_inv y_inv yaw_inv
"""
r_yaw = -yaw
r_x = -(math.cos(-yaw)*x - math.sin(-yaw) * y)
r_y = -(math.sin(-yaw)*x + math.cos(-yaw) * y)
prBlue("input:%f,%f,%f" % (x,y,yaw))
prRed("output:%f,%f,%f" % (r_x,r_y,r_yaw))
return (r_x,r_y,r_yaw)
def Pose2dInverse1(x,y,yaw) :
r_yaw = -yaw
r_x = -(math.cos(-yaw)*x - math.sin(-yaw) * y)
r_y = -(math.sin(-yaw)*x + math.cos(-yaw) * y)
result = "%f,%f,%f" % (r_x,r_y,r_yaw)
prRed(result)
return result
测试类
测试类
//获取Person类
PyObject *pClassPerson = PyObject_GetAttrString(pModule, "Person");
//创建Person类的实例
PyObject *pConstruct = PyInstance_New(pClassPerson, NULL, NULL); //python2
// PyObject *pConstruct = PyInstanceMethod_New(pClassPerson); //python3
PyObject *pInstancePerson = PyObject_CallObject(pConstruct, NULL);
//调用方法
PyObject_CallMethod(pInstancePerson, "greet", "s", "Hello Kitty"); //s表示传递的是字符串,值为"Hello Kitty"
python 代码:
class Person:
class
def sayHi(self):
print("Hi!")
def greet(self,obj):
print("greet:%s" % obj)
class Second:
def invoke(self,obj):
obj.sayHi()
def sayhi(name):
print 'hi',name;
测试案例
#include "gtest/gtest.h"
#include "glog/logging.h"
#include "Python.h"
#include "../../common/config.h"
namespace hybrid_slam {
namespace {
void PythonTest(){
// 使用python之前,要调用Py_Initialize();这个函数进行初始化
Py_Initialize();
// 判断初始化是否成功
if(!Py_IsInitialized()) {
LOG(ERROR)<<"python init failed !";
return ;
}
// 添加python文件所在的位置
std::string python_path = std::string(common::kSourceDirectory) + "/hybrid_slam/tmp/";
PyRun_SimpleString("import sys"); // 导入sys库
std::string cmd_path = "sys.path.append(\"" + python_path + "\")";
LOG(INFO)<<"path: "<<cmd_path;
PyRun_SimpleString(cmd_path.c_str()); // 添加环境变换
PyObject *pModule = NULL; //声明变量
PyObject *pFunc = NULL; //声明变量
pModule = PyImport_ImportModule("test_c"); //这里是要调用的Python文件名
if(!pModule) {
LOG(ERROR)<<"can not open python file";
return ;
}
// 测试 HelloWorld
pFunc = PyObject_GetAttrString(pModule, "TestPrint"); //这里是要调用的函数名
PyEval_CallObject(pFunc, NULL); //调用函数,NULL表示参数为空
// 测试 Add,传两个int型参数
pFunc = PyObject_GetAttrString(pModule, "TestAdd"); //Add:Python文件中的函数名
{
//创建参数:
PyObject *pArgs = PyTuple_New(2); //函数调用的参数传递均是以元组的形式打包的,2表示参数个数
PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", 5)); //0---序号 i表示创建int型变量
PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", 7)); //1---序号
//返回值
PyObject *pReturn = NULL;
pReturn = PyEval_CallObject(pFunc, pArgs); //调用函数
if(pReturn) {
//将返回值转换为int类型
int result;
if(PyArg_Parse(pReturn, "i", &result)) { //i表示转换成int型变量
LOG(INFO)<<"5+7 = "<<result;
ASSERT_EQ(result,12);
} else {
LOG(ERROR)<<"TestAdd return trans int error";
}
} else {
LOG(ERROR)<<"TestAdd return nullptr";
}
}
// 测试 2d 位姿取逆
pFunc = PyObject_GetAttrString(pModule, "Pose2dInverse1"); //Add:Python文件中的函数名
{
PyObject *pArgs = PyTuple_New(3);
PyTuple_SetItem(pArgs, 0, Py_BuildValue("d", 1.));
PyTuple_SetItem(pArgs, 1, Py_BuildValue("d", 2.));
PyTuple_SetItem(pArgs, 2, Py_BuildValue("d", 30./180*3.1415926));
//返回值
PyObject *pReturn = NULL;
pReturn = PyEval_CallObject(pFunc, pArgs); //调用函数
if(pReturn) {
LOG(INFO)<<"Pose2dInverse1 have result";
//将返回值转换为int类型
const char* result;
if(PyArg_Parse(pReturn, "s", &result)) {
std::string sss(result);
LOG(INFO)<<"Pose2dInverse1 : "<<sss;
} else {
LOG(ERROR)<<"Pose2dInverse1 trans double3 error";
}
} else {
LOG(ERROR)<<"Pose2dInverse1 return nullptr";
}
}
// 测试 2d 位姿取逆
pFunc = PyObject_GetAttrString(pModule, "Pose2dInverse"); //Add:Python文件中的函数名
{
PyObject *pArgs = PyTuple_New(3);
PyTuple_SetItem(pArgs, 0, Py_BuildValue("d", 1.));
PyTuple_SetItem(pArgs, 1, Py_BuildValue("d", 2.));
PyTuple_SetItem(pArgs, 2, Py_BuildValue("d", 30./180*3.1415926));
//返回值
PyObject *pReturn = NULL;
pReturn = PyEval_CallObject(pFunc, pArgs); //调用函数
if(pReturn) {
//将返回值转换为int类型
double result[3];
if(PyArg_ParseTuple(pReturn, "ddd", &result[0],&result[1],&result[2])) {
LOG(INFO)<<"0result: "<<result[0]<<" "<<result[1]<<" "<<result[2];
} else {
LOG(ERROR)<<"Pose2dInverse trans double3 error";
}
} else {
LOG(ERROR)<<"Pose2dInverse return nullptr";
}
}
Py_DECREF(pFunc);
// class Person:
// class
// def sayHi(self):
// print("Hi!")
// def greet(self,obj):
// print("greet:%s" % obj)
// class Second:
// def invoke(self,obj):
// obj.sayHi()
// def sayhi(name):
// print 'hi',name;
PyObject* pDict = PyModule_GetDict(pModule);
if (!pDict) {
LOG(ERROR)<<"Cant find dictionary.";
}
PyObject* pFunHi = PyDict_GetItemString(pDict, "sayhi");
PyObject_CallFunction(pFunHi, "s", "lyb");
Py_DECREF(pFunHi);
// 获取Second类
PyObject* pClassSecond = PyDict_GetItemString(pDict, "Second");
if (!pClassSecond) {
printf("Cant find second class./n");
return ;
}
//获取Person类
PyObject* pClassPerson = PyDict_GetItemString(pDict, "Person");
if (!pClassPerson) {
printf("Cant find person class./n");
return ;
}
//构造Second的实例
PyObject* pInstanceSecond = PyInstance_New(pClassSecond, NULL, NULL);
if (!pInstanceSecond) {
printf("Cant create second instance./n");
return ;
}
//构造Person的实例
PyObject* pInstancePerson = PyInstance_New(pClassPerson, NULL, NULL);
if (!pInstancePerson) {
printf("Cant find person instance./n");
return ;
}
//把person实例传入second的invoke方法
PyObject_CallMethod(pInstanceSecond, "invoke", "O", pInstancePerson);
//获取Person类
//创建Person类的实例
PyObject *pConstruct = PyInstance_New(pClassPerson, NULL, NULL); //python2
// PyObject *pConstruct = PyInstanceMethod_New(pClassPerson); //python3
PyObject *pInstancePerson1 = PyObject_CallObject(pConstruct, NULL);
// 使用元组 args 给出的参数调用可调用的Python对象 callable 。如果不需要参数,则 args 可以为 NULL 。
// 成功时返回调用结果,或引发异常,失败时返回 NULL 。
// 这等效于Python表达式:callable(*args)。
//调用方法
PyObject_CallMethod(pConstruct, "greet", "s", "Hello Kitty"); //s表示传递的是字符串,值为"Hello Kitty"
Py_DECREF(pInstanceSecond);
Py_DECREF(pInstancePerson);
Py_DECREF(pClassSecond);
Py_DECREF(pClassPerson);
//调用Py_Finalize,这个和Py_Initialize相对应的.
Py_Finalize();
}
}
TEST(pythonTest, python_function_test){
PythonTest();
}
}