C++调用python,并抓取每日一句名言

追求适度,才能走向成功;人在顶峰,迈步就是下坡;身在低谷,抬足既是登高;弦,绷得太紧会断;人,思虑过度会疯;水至清无鱼,人至真无友,山至高无树;适度,不是中庸,而是一种明智的生活态度。

导读:本篇文章讲解 C++调用python,并抓取每日一句名言,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

作者:非妃是公主
专栏:《笔记》《C++》 《python学习》
个性签:顺境不惰,逆境不馁,以心制境,万事可成。——曾国藩

在这里插入图片描述

前言

前几天利用C++调用Python脚本,在进行语言融合的过程中,踩到了好多坑,在此总结一下!

C++执行python代码

  • 首先我们需要配置C++调用python所需要的链接库,将include和libs文件夹放到工程文件目录下(和.sln文件放在一起)
    在这里插入图片描述
  • 两个文件在python的安装目录下,比如我的:
    在这里插入图片描述
  • 在项目中配置环境依赖
    右键项目-》选择属性-》C/C+±》常规-》附加包含目录,添加include文件夹的相对路径(../include),../为返回上一级目录。(当前cpp的上一级目录就是include所在目录)
    在这里插入图片描述
    右键项目-》选择属性-》选择连接器-》常规-》附加库目录-》添加libs的相对目录../libs../为返回上一级目录。(当前cpp的上一级目录就是libs所在目录)。

在这里插入图片描述

  • 点击应用,然后关闭窗口,编译器切换到release,选择64位,这块要根据子集python的版本,因为我的是64位,就只能在MSVC64的环境下运行,而且我的python没有安装python在MSVC下的调试器,所以只能在release下运行(如果安装的时候没有特别注意,都是我这样安装的)。
    在这里插入图片描述
  • 运行下面的代码
    在这里插入图片描述
#include <Python.h>
int main(int argc, char* argv[]) {
	Py_Initialize();
	PyRun_SimpleString("print('hello world')\n");
	Py_Finalize();
	return 0;
}
  • 控制台弹出以下信息
    在这里插入图片描述
    这是在说明,我们没有设置PYTHONHOMEPYTHONPATH这两个环境变量。
    新建PYTHONHOME用户变量,变量值设置为Anaconda3所在的目录下即可(为了找到python.exe)
    在这里插入图片描述
    同样,新建PYTHONPATH用户变量,变量值与PYTHONHOME相同
    这样用户变量就配置好了。
    在这里插入图片描述
    重新运行,发现还是报错(这是由于环境变量需要重启后才能生效,重启电脑)。
    在这里插入图片描述
  • 重启电脑后,发现运行正常了,打出了Hello World这里注意一下,这个环境变量会对虚拟环境造成影响,如果用完之后要用其它虚拟环境,一定要注意删除这两个环境变量,否则会产生无法识别的错误这篇文章中有记录不删除这两个环境变量会产生的问题
    在这里插入图片描述
  • 对以上代码进行简单的说明,如下图:
    在这里插入图片描述
  • 上面我们解决了如何利用C++执行python代码的问题,那么很多时候我们的python代码都是比较复杂的(包括分支循环,作用域等),用字符串表示起来是不方便的,是否可以存在一种可以直接调用py文件的方法呢?答案是肯定的。

C++调用.py文件

我们新建C++工程,然后按照上面进行目录的配置(libs和include),编译环境的切换(release,X64)。
然后新建.py文件,并放在工程文件名/X64/release文件夹下,与工程的.exe文件放在一起,不然会找不到。
在这里插入图片描述

在这里插入图片描述
代码如下:

#include <Python.h>
#include <iostream>
#include <string>
using namespace std;

int main(int argc, char* argv[]) {
	Py_Initialize();// Python 接口初始化

	PyObject* pModule = NULL; // 模块句柄
	PyObject* pFunc = NULL;// 函数句柄
	PyObject* pName = NULL;// 
	pModule = PyImport_ImportModule("Test"); // 文件名
	if (pModule == NULL) // 如果没找到返回
	{
		cout << "没找到" << endl;
		return 0;
	}
	pFunc = PyObject_GetAttrString(pModule, "Fun"); // 函数名
	PyObject* pArgs = PyTuple_New(2);// 函数调用的参数传递均是以元组的形式打包的,2表示参数个数
	PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", 222));// 0 表示第一个参数 i表示 int类型 222表示具体参数
	PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", 444));// 1 表示第二个参数 i表示 int类型 444表示具体参数
	PyObject* pReturn = PyObject_CallObject(pFunc, pArgs);// 调用函数

	int nResult;// 储存结果的C++类型
	PyArg_Parse(pReturn, "i", &nResult);// i表示转换成int型变量
	cout << nResult << endl; // 输出
	Py_Finalize();// 结束Python接口初始化
	return 0;
}

至于返回值的传递是一个比较麻烦的问题,由于这是一个老接口了,所以并不是很好用,在参数传递的过程中我踩了好多坑,最终一种比较好用的解决方法就是将返回值写进文件,然后在C++中写代码去读文件,当然这样效率会比较低,但是相信使用C++和python进行语言融合的项目都是想短期实现,对性能要求不高的。自己写的一个爬虫程序效果如下:
每运行一次OneNoteEveryDay.exe会生成一个OneNoteEveryDay.txt。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

C++调用爬虫

爬虫代码如下,有兴趣的友友可以尝试一下,还挺好玩的!(^o^)!

import random
from bs4 import BeautifulSoup
import requests
import ctypes as ct
import re


def Fun():
    res = requests.get('http://quotes.toscrape.com/')
    res.raise_for_status()
    html = res.text  # 页面内容
    soup = BeautifulSoup(html, 'lxml')

    items = soup.find_all('span', class_='text')
    words = []

    for item in items:
        words.append(item.text)
        # f.write(output + '\n')

    f = open("OneNoteEveryDay.txt", 'w')
    number = random.randint(0, len(words) - 1)
    words[number] = re.sub("“", "", words[number])
    words[number] = re.sub("”", "", words[number])
    f.write(words[number])
    f.close()

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之家整理,本文链接:https://www.bmabk.com/index.php/post/130542.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之家——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!