go加载python_python培训 | python调用go语言来提速

在写一些对性能要求十分严格的功能的时候,python往往力不从心。毕竟是一个解释性的语言,没有办法和变异性的语言去比较速度和内存占用率。但是python的本身的特定就使得我们可以将耗时的操作移交给编译性的语言去实现。由于项目上的关系,需要对迸发有着比较严格的要求,所以想到了go语言。这里介绍一下如何使用python调用go语言的代码。python调用go语言是通过c语言实现的,可以将go语言打包成so,然后让python通过ctypes加载so文件来实现python调用go语言。这里介绍在linux上实现的方式,在windows上,应该需要改变编译的指令。首先是go方面的代码:main.go文件package mainimport "C"import "fmt"//export Sumfunc Sum(a, b int) int {    return a + b}//export Testfunc Test() int {    var s int   for i := 0; i < 1000000; i++ {       s += i   }    return s}func main() {   fmt.Println(Test())}其中Sum函数上方的//export Sum是必须的,没有这个注释,不会被识别成为导出的对象。export后面的字符是导出后的名字。import "C"也是必须的。

使用如下指令编译:go build -buildmode=c-shared -o sum.so main.gosum.so是编译后的文件,main.go是要编译的文件。

编译完成后,会在当前目录生成sum.so,和sum.h文件。

这里来看一下sum.h文件,下面截取了一段关键的代码:#ifdef __cplusplusextern "C" {#endifextern GoInt Sum(GoInt p0, GoInt p1);extern GoInt Test();#ifdef __cplusplus}#endif可以看到导出了一个Sum函数和一个Test函数,如果不写//export funcname是不会有这个的。

将sum.so和sum.h放到python的目录下面。然后再来编辑test.py文件,这个文件和sum.so同目录下即可。

test.pyfrom ctypes import CDLLimport ctypesif __name__ == "__main__":   test = CDLL("./sum.so").Test   test.restype = ctypes.c_int64   print(test())使用CDLL("./sum.so")加载so模块,然后使用.Test导向Test函数,这里必须和sum.h里一致。test.restype = ctypes.c_int64将Test的函数返回类型声明为int64,在这里的机器上,默认的结果使用的返回类型为int32,会得到一个错误的结果。需要显示的声明为int64。

最后使用test()来调用。运行程序,查看结果。

d80a6cac3e811c55ebd793e20cf8d79c.png

除了上面的定义返回值得类型,还可以定义传入参数的类型,上面的代码中,还定义了一个sum函数。

sum = CDLL("./sum.so").Sum   sum.argtypes = [ctypes.c_int32, ctypes.c_int32]   sum.restype = ctypes.c_int32   print(sum(1, 2))argtypes将接受一个列表类型,里面是各个参数的类型。

来测试一下调用go语言代码的速度,和用python自己写的速度有什么区别。from ctypes import CDLLimport ctypesimport datetimedef speedTest():   sum = 0   for i in range(1000000):       sum += i    return sumif __name__ == "__main__":   test = CDLL("./sum.so").Test   test.restype = ctypes.c_int64   start = datetime.datetime.now()    for i in range(10):       test()   end = datetime.datetime.now()   print(end - start)   start = datetime.datetime.now()    for i in range(10):       speedTest()   end = datetime.datetime.now()   print(end - start)   print("done")go的代码就不放出来了,和python一样,也就用for循环计算累加1000000的值。其实这里的测试不太严谨,但是不影响粗略来看测试的结果。可以发现,两者的速度根本就不是一个数量级的。这还仅仅只是时间上的差距,内存上的差距还没有去看。所以如果对项目的耗时非常严格的话,不妨将其中的耗时操作交给go甚至是c语言去实现,能极大提升性能。

一般来说往函数传递参数的时候,不只是需要传递int值,需要穿钉string值。这个时候问题就来了,传递一个string值会怎么样?//export printStringfunc printString(a string) {   fmt.Println(a)}来看看头文件:#ifdef __cplusplusextern "C" {#endifextern void printString(GoString p0);#ifdef __cplusplus}#endif可以看到函数的参数类型为GoString,这个类型是c语言没有的。往上翻翻能看到GoString的定义:typedef struct { const char *p; ptrdiff_t n; } _GoString_;是一个结构体,有一个char类型的指针和一个代表长度的整数n。

那么在调用这个函数的时候,就需要传递一个GoString的值进去。python侧需要自己来写这个结构体定义。class GoString(ctypes.Structure):   _fields_ = [("p", ctypes.c_char_p), ("n", ctypes.c_longlong)]接下去构建参数传递:msg = GoString(b"hello,world!",len(b"hello,world!"))printString(msg)这里得使用字节流才行,因为是C的char类型指针。最后设置接收类型为定义好的GoString就能调用了。同理,也可以把返回值设置为string,在python里面也可以用这个GoString这个类给读出来。但是直接输出会输出一个内存地址,需要用result.p来输出,这个也是一个字节流。

其他诸如go的map和chan,在导出的时候,都会被标识为void *,读取起来非常麻烦,而slice需要一个结构体来实现。class GoSlice(Structure):    _fields_ = [("data", POINTER(c_void_p)), ("len", c_longlong), ("cap", c_longlong)]最后说一下限制,go语言写的结构体,是没有办法导出的,所以结果的交互要用结构体的时候,尽量用json之类的封装一下。

声明:

由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,雷神众测以及文章作者不为此承担任何责任。雷神众测拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经雷神众测允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。

注释:本文来自公众号雷神众测

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/555852.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot框架中使用Jackson的处理总结

1.前言 通常我们在使用Spring Boot框架时&#xff0c;如果没有特别指定接口的序列化类型&#xff0c;则会使用Spring Boot框架默认集成的Jackson框架进行处理&#xff0c;通过Jackson框架将服务端响应的数据序列化成JSON格式的数据。 本文主要针对在Spring Boot框架中使用Jac…

SpringBoot中对输出的json按字典表排序

SpringBoot中对输出的json按字典表排序 springboot默认的json处理为jackson。 如果是全局设置&#xff0c;在application.properties中添加spring.jackson.mapper.sort-properties-alphabeticallytrue

Java hdfs连接池_Java使用连接池管理Hdfs连接

记录一下Java API 连接hadoop操作hdfs的实现流程(使用连接池管理)。以前做过这方面的开发&#xff0c;本来以为不会有什么问题&#xff0c;但是做的还是坑坑巴巴&#xff0c;内心有些懊恼&#xff0c;记录下这烦人的过程&#xff0c;警示自己切莫眼高手低&#xff01;一&#x…

为了拿捏 Redis 数据结构,我画了 40 张图(完整版)

Redis 为什么那么快&#xff1f; 除了它是内存数据库&#xff0c;使得所有的操作都在内存上进行之外&#xff0c;还有一个重要因素&#xff0c;它实现的数据结构&#xff0c;使得我们对数据进行增删查改操作时&#xff0c;Redis 能高效的处理。 因此&#xff0c;这次我们就来…

java put set_Java PutItemRequest.setItem方法代码示例

import com.amazonaws.services.dynamodbv2.model.PutItemRequest; //导入方法依赖的package包/类public List reindex(T instance) throws DataStoreException {DynamoClassMapping tableInfo getClassMapping(instance);log.debug("reindex {}", instance.getClas…

fastjson为什么默认是无序的

在做项目的时候&#xff0c;无意间发现添加到json中的元素是无存放顺序的。严格来说&#xff0c;json默认是有存放顺序的&#xff0c;不过是采用HashCode值来排序。下面来看一段源码 上图展示了创建json对象的一个过程&#xff0c;可以清晰的看出&#xff0c;无论用户调用哪个…

php一句话怎么写_PHP一句话木马后门

在我们进行渗透测试的最后阶段&#xff0c;入侵到内网里&#xff0c;无论是想要浏览网站结构&#xff0c;还是抓取数据库&#xff0c;或者是挂个木马等等&#xff0c;到最后最常用的就是执行一句话木马&#xff0c;从客户端轻松连接服务器。一句话木马的原理很简单&#xff0c;…

JSON书写格式

JSON是什么 JSON ( JavaScript Object Notation) &#xff0c;是一种数据交互格式。 为什么有这个技术 Json之前&#xff0c;大家都用 XML 传递数据。XML 是一种纯文本格式&#xff0c;所以适合在网络上交换数据&#xff0c;但是 XML 格式比较复杂&#xff0c;终于道格拉斯克…

php判断目录是否有写的权限,php中判断文件空目录是否有读写权限

/*问题出现&#xff1a;如何检查一个目录是否可写&#xff0c;如何目录下还有目录和文件&#xff0c;那么都要检查思路&#xff1a;(1)首先先写出检查空目录是否可写的算法&#xff1a;在该目录中生成一个文件&#xff0c;如果不能生成&#xff0c;表明该目录没有写的权限(2)使…

List.addAll方法的入参不能为null

缘由&#xff1a; ​ 某天&#xff0c;发现一段日志中出现了诡异的NPE。经过定位&#xff0c;认为是ArrayList不能加入null所致。 验证&#xff1a; ​ new一个ArrayList&#xff0c;然后调用其addAll方法&#xff0c;并将入参设为null。 public static void main(String[] …

php 微信转账,php实现微信公众号企业转账功能

企业付款提供由商户直接付钱至用户微信零钱的能力&#xff0c;支持平台操作及接口调用两种方式&#xff0c;资金到账速度快&#xff0c;使用及查询方便。主要用来解决合理的商户对用户付款需求&#xff0c;比如&#xff1a;保险理赔、彩票兑换等等。特点发起方式灵活&#xff0…

Java之HashMap.values()转List时的错误和正确操作

因为项目中需要获取到Map的值的集合&#xff0c;所以调用了HashMap.values()方法转成List&#xff0c;当时是使用了以下代码。&#xff08;逻辑上这样想应该没问题&#xff0c;但生活总是会是不是给你一点小“”惊喜“”&#xff09; List<AreaItemOpt> areaItemOpts (…

php检测表大小,查询mysql数据库、表的大小

一、关于mysql表数据大小mysql存储数据文件一般使用表空间存储 &#xff1b;当mysql使用innodb存储引擎的时候&#xff0c;mysql使用表存储数据分为共享表空间和独享表空间两种方式 。共享表空间&#xff1a;Innodb的所有数据保存在一个单独的表空间里面&#xff0c;而这个表空…

Java利用stream(流)对map中的values进行过滤、排序操作

前言 对于Java8中的stream(流)这种优雅、方便、快捷、高效的操作已经是信手沾来了吧&#xff0c;但是却仅限List、Set。难道我Map不要面子得嘛&#xff1f;在工作中需要对从List转Map的数据进行操作&#xff0c;因此便有这随笔。 新建一个User类&#xff0c;注意下面使用lombok…

cls certificate.php,php加密解密处理类

PHP加密解密也是常有的事&#xff0c;发现discuz论坛里的PHP加密解密处理类代码&#xff0c;感觉挺不错&#xff0c;在用的时候&#xff0c;要参考Discuz论坛的passport相关函数&#xff0c;后面我会附上使用方法。php加密解密处理类<?php /* 文件名称&#xff1a;cls.sys_…

【redis】java操作redis时,StringRedisTemplate的expire()方法的作用,什么时候使用

java操作redis时&#xff0c;StringRedisTemplate的expire()方法的作用&#xff0c;什么时候使用 //重新设置过期时间为30分钟&#xff0c;刷新时间 redisTemplate.expire(MsOpenApiRedisUtil.SESSION_KEY_IN_LOGIN_NAMEloginName,30,TimeUnit.MINUTES); redisTemplate.expire…

springboot使用redis(StringRedisTemplate的常用方法)

1. 先了解RedisTemplate和StringRedisTemplate之间的关系&#xff1a; RedisTemplate是Spring对于Redis的封装&#xff0c;而StringRedisTemplate继承RedisTemplate。两者的数据是不共通的&#xff1b;也就是说StringRedisTemplate只能管理StringRedisTemplate里面的数据&…

html提交表单给php邮件发送,在HTML表单中通过PHP自动发送电子邮件

我最终解决了我的问题吧一个细节。我的HTML帖子回答:Navn: Kontakt e-post: Kontakt telefon: Fest:LokalfestHjemmefestKommune: Deltagere: Rydding: Vasking: Dorvakt: Noe annet?: 我的PHP帖子回答:if(isset($_POST[mailform]))$email $_POST[Epost] ;$name $_POST[Navn…

Arrays.asList()和Collections.singletonList()比较

Collections.singletonList(something)是不可变的&#xff0c; 对Collections.singletonList(something)返回的列表所做的任何更改将导致UnsupportedOperationException。 Arrays.asList(something)允许Arrays.asList(something) 更改 。 此外&#xff0c;由Collections.sin…

php 邮件类库,[3.3]-扩展类库:基于PHPMailer的邮件发送 | PhalApi(π框架) - PHP轻量级开源接口框架 - 接口,从简单开始!...

3.3.1 扩展类库&#xff1a;基于PHPMailer的邮件发送此扩展可用于发送邮件。3.3.2 安装和配置从 PhalApi-Library 扩展库中下载获取 PHPMailer 包&#xff0c;如使用&#xff1a;$ git clone https://git.oschina.net/dogstar/PhalApi-Library.git然后把 PHPMailer 目录复制到 …