Home > Backend Development > Golang > [Advanced] Python+Go - Let's find another way to improve computing performance

[Advanced] Python+Go - Let's find another way to improve computing performance

Release: 2023-07-20 16:32:25
forward
752 people have browsed it
In the previous article, we successfully called the Go code through Python and handed over the intensive calculation to Go for calculation Calculation, although the calculation is very fast, when getting the return value, it seems a bit surprising, not what we imagined.

[Advanced] Python+Go - Let's find another way to improve computing performance


##/2 What is the reason for the return value error? /

In the last article, we seemed to have forgotten a picture.

[Advanced] Python+Go - Let's find another way to improve computing performance


The .go file belongs to Go. Without further ado, .so is the file used by Python to call Go. What is the .h file? ? ? It seems to have no sense of existence. Our problem lies in this .h file. Let’s open it and take a look

[Advanced] Python+Go - Let's find another way to improve computing performance


## We scroll down and we will find the statement starting with extern. This means converting the Go code into C code with one-to-one corresponding parameters. It can be seen that what is converted to C is the GoInt type. What does this type mean? ? ? ? Look again.

[Advanced] Python+Go - Let's find another way to improve computing performance

In fact, you can probably find out from the above that GoInt is actually GoInt64, and the type of GoInt64 is long long type. Is this a thing? ? ?

Actually, when we call the .so file in Python, we use the <span style="font-size: 18px;">ctypes</span> module. This is There is a correspondence table.

[Advanced] Python+Go - Let's find another way to improve computing performance


##/3 Python, ctypes, c type Correspondence table/

Official website address:

https://docs.python.org/3.5/library/ctypes.html
Copy after login


ctypes typeC typePython type
c_bool_Boolbool (1)
c_charchar1-character  bytes object
c_wcharwchar_t1-character  string
c_bytecharint
c_ubyteunsigned charint
c_shortshortint
c_ushortunsigned shortint
c_intintint
c_uintunsigned intint
c_longlongint
c_ulongunsigned longint
c_longlong__int64 or long longint
c_ulonglongunsigned  __int64 or unsigned long longint
c_size_tsize_tint
c_ssize_tssize_t or Py_ssize_tint
c_floatfloatfloat
c_doubledoublefloat
c_longdoublelong doublefloat
c_char_pchar * (NUL  terminated)bytes object  or None
c_wchar_pwchar_t * (NUL  terminated)string or None
c_void_pvoid *int or None


根据上述表格我们可以发现,在C中的long long类型对应的ctype类型是c_longlong。

[Advanced] Python+Go - Let's find another way to improve computing performance


所以我们需要在Python将.so中的返回值改一下,不能使用系统默认的了。代码如下:

from ctypes import *
import time

class StructPointer(Structure):
    # 根据查表,C中的long long,对应的ctypes 是 c_longlong
    # _fields_必须是[](列表)类型,里面写对应的类型,固定格式
    _fields_ = [("p", c_longlong,),]

if __name__ == &#39;__main__&#39;:
    beginTime = time.time()
    s = CDLL("s1.so")  # 加载s1.so文件
    s.run.restype = StructPointer # 声明.so的run函数返回值类型,固定格式
    result = s.run(100000000)  # 调用Go生成的.so文件里面的run函数

    print("result:", result.p)# 此处需要调用.p来获取值,和 _fields_对应
    endTime = time.time()
    print("耗时:", endTime - beginTime)
Copy after login


再次执行:

[Advanced] Python+Go - Let's find another way to improve computing performance

可以看到,这次Python执行的结果和Go执行结果就一个样了。继续,换个数字试试看。

[Advanced] Python+Go - Let's find another way to improve computing performance

基本可以确定,这次是没问题了。


/4 如果返回的是字符串呢?/

Go代码

package main

import (
  "C" //C必须导入
  "fmt"
)

//export run
func run(n int) int{
  /*
    必须要export 函数名
    //是注释的意思,相当于Python中的 #
    我也是第一次见注释还有作用
  */
  sum := 0
  for i := 0; i < n; i++ {
    sum += i
  }
  fmt.Println("我是Go代码,我跑完了,我的结果是:",sum)
  return sum
}

//export speak
func speak(n int) string{

  return "OMG 996好累呀,难得休息一天,好好休息"
}
func main() {
  //main函数中什么都不要写,和包名main要对应
}
Copy after login


下面一起来理解.h文件。编译之后打开.h文件如下图所示:

[Advanced] Python+Go - Let's find another way to improve computing performance


可以看到,在extern的函数成了两个,但是他的返回值是GoString,继续找。

[Advanced] Python+Go - Let's find another way to improve computing performance


可以发现,其实GoString就是_GoString_,继续找。

[Advanced] Python+Go - Let's find another way to improve computing performance

这次是一个结构体,里面其实是两个值,不在是单独的long long了,那Python中的继承类也要改一下了。

[Advanced] Python+Go - Let's find another way to improve computing performance


下面基本同上。

[Advanced] Python+Go - Let's find another way to improve computing performance

完整代码如下:

from ctypes import *
import time

class StructPointer(Structure):
    # 根据查表,C中的long long,对应的ctypes 是 c_longlong
    # _fields_必须是[](列表)类型,里面写对应的类型,固定格式
    _fields_ = [("p", c_longlong,),]

class StrPointer(Structure):
    # typedef struct { const char *p; ptrdiff_t n; } _GoString_;
    # ptrdiff_t == long long
    _fields_ = [("p", c_char_p), ("n", c_longlong)]

if __name__ == &#39;__main__&#39;:
    beginTime = time.time()
    s = CDLL("s1.so")  # 加载s1.so文件

    s.run.restype = StructPointer # 声明.so的run函数返回值类型,固定格式
    result = s.run(100000798)  # 调用Go生成的.so文件里面的run函数
    print("result:", result.p)# 此处需要调用.p来获取值,和 _fields_对应

    s.speak.restype = StrPointer
    speakStr = s.speak()
    # 返回的是字节类型,需要转字符串,返回的内容在.p中,.n是切的长度,后面会跟一些介绍,不需要
    speakStr = str(speakStr.p[:speakStr.n], encoding="utf-8")
    print("speak:",speakStr)

    endTime = time.time()
    print("耗时:", endTime - beginTime)
Copy after login


结果:

[Advanced] Python+Go - Let's find another way to improve computing performance

    可以看到,调用Go代码成功的拿到了正确的字符串返回值,如果没有 .restype = StrPointer拿到的会是什么呢?拿到会和原来的一样,一堆数字,这里就不举栗子了。


/5 小结/

    至此,基本上在Python调用Go代码上的大坑都解决了,最复杂的是返回字符串类型,查了很多相关资料才解决。

    关于返回其他类型的Python的class怎么写,我相信已经难为不到你们了,最复杂的都解决了,最简单的还不会吗?(除字符串类型以外其他_fields_都是一个字段的)

    我相信各位小伙伴学习能力还是很强的,人生苦短,Python当歌,加油,奥利给!

The above is the detailed content of [Advanced] Python+Go - Let's find another way to improve computing performance. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:Go语言进阶学习
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template