python附加篇cpython用法

心得:刚换工作后,连续忙了2个多月,在这两个多月里,学到的东西也是比较多的,不论从算法上,源码调试上,还是代码规范性上都有一定的提升,接下来会将这段时间接触到内容逐一记录下来。先从cpython开始吧,cpython用作代码保护或者能够提升代码运行的效率。

Cpython官网:https://cython.readthedocs.io/en/latest/index.html

中文版:https://cython.apachecn.org/#/docs/29?id=%e5%9f%ba%e6%9c%ac-setuppy

一、Cpython简介

CPython是特指C语言实现的Python,就是原汁原味的Python。主要目的做python的加速,当然在编译后,相应的对代码进行了保护

二、快速开始,配置文件以及编译

创建pyx文件:

hello.pyx

import time

t0 = time.time()
for i in range(100000):
    pass
print("time is {}".format(time.time()-t0))

setup.py

from setuptools import setup
from Cython.Build import cythonize

setup(
    ext_modules=cythonize("hello.pyx")
)

命令行输入python setup.py build_ext --inplace对hello.pyx文件进行编译
将会生成hello.的so动态库,我们调用此so动态库即可。
在这里插入图片描述
test.py

import hello

cpython 输出
time is 0.002833843231201172

我们用python同样输出
time is 0.005338907241821289

速度提高了一半左右,要是将大量的计算方入编译,速度会有较高的提升

三、cpython中编码注意事项

Python类型list,dict,tuple,等等可被用于静态类型

变量类型定义,在pyx文件中定义好了才可以调用

cdef list foo = []
cdef dict fol = {}
cdef (double, int) bar

在函数中,如果未为参数或返回值指定类型,则假定该类型为Python对象。所以最好在入参和返回值的时候定义变量类型

hello.py 如果变量输出类型未定义则会输出None

cdef list l=[1,2,3]

def lis(int x,int y):
    cdef dict c ={}
    a = x + y
    l.append(a)
    c["lis"] = l
    return c

输出:

{'lis': [1, 2, 3, 3]}

cpython中比如定义了列表,但经过编译后,没办法正常调用此列表,正确的方式是用函数去返回,用函数将列表包装再返回。

也可以使用声明类cdef,使它们成为Extension Types,它们的行为非常接近python类,但是速度更快,因为它们使用struct 内部存储属性。

from __future__ import print_function

cdef class Shrubbery:
    cdef list width, height

    def __init__(self, w, h):
        self.width = w
        self.height = h

    def describe(self):
        print("This shrubbery is", self.width,
              "by", self.height, "cubits.")

编译后test.py

import new

res = new.Shrubbery([1,2],[])
res.describe()

##输出
This shrubbery is [1, 2] by [] cubits.

注意:将类编译到cpython中后,从外面调用编译过的类属性是拿不到的,如果想拿对应的类属性,可以编写对应的方法来获取属性。

cdef class Shrubbery:
    cdef list width, height

    def __init__(self, w, h):
        self.width = w
        self.height = h
        print(self.width,"width")
        print("my friends: ",my_friends())

    def describe(self):
        print("This shrubbery is", self.width,
              "by", self.height, "cubits.")

    def get_width(self):
        return self.width
shr = hello.Shrubbery([1,2],[3,4])
shr.describe()
print("width",shr.get_width())

四、编译

1. 基本的setup.py

如果只有一个Cython文件要转换为已编译的扩展名,则使用filename example.pyx表示关联setup.py 如下:

from setuptools import setup
from Cython.Build import cythonize

setup(
    ext_modules = cythonize("example.pyx")
)

编译:$ python setup.py build_ext --inplace

2. 包中的多个Cython文件

若要自动编译多个Cython文件而不显式列出所有文件,可以使用全局模式:

setup(
    ext_modules = cythonize("package/*.pyx")
)

Extension如果通过它们,也可以在对象中使用全局模式cythonize():

extensions = [Extension("*", ["*.pyx"])]

setup(
    ext_modules = cythonize(extensions)
)

3. 多个包时,setup文件编写

参考地址

from setuptools import Extension, setup
from Cython.Build import cythonize

setup(
    ext_modules=cythonize("hello.pyx")
)

# include_dirs,libraries和library_dirs,它们指定链接到外部库时在哪里可以找到.h和库文件。
# module_list 可以是多个Extension也就是多个pyx文件
ext_modules = cythonize(module_list=[
    Extension(name="chello",
              sources=["test.pyx"],
              libraries=["hello"],
              include_dirs=['c2/include'],
              library_dirs=['c2/lib']
              ), ])

# ext_modules 要构建的 Python 扩展的列表
# packages distutils将操作的Python软件包列表, 按包分发,其他的还是元数据,其中name最好是一定要到,如果安装的话生成的文件会是指定name的名字
setup(name='chello',
      version="1.1.0",
      author="作者",
      ext_modules=ext_modules,
      description='Python Distribution Utilities',
      author_email='',
      url='',
      packages=['distutils', 'distutils.command']
      )

  • 7
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
CPythonPython 的官方实现,它是用 C 语言实现的。如果你安装了 Python,那么你已经安装了 CPython。你可以在命令行中输入 `python` 来启动 CPython 解释器。 使用 CPython,你可以编写 Python 代码,并执行它们。你还可以使用 C 或 C++ 编写 Python 扩展模块,以扩展 Python 的功能。为了编写扩展模块,你需要使用 Python 的 C API,这些 API 允许你在 C 或 C++ 中操作 Python 对象。 下面是一个使用 CPython 的示例: ```python # hello.py print("Hello, world!") ``` 你可以在命令行中使用以下命令来执行 hello.py: ``` $ python hello.py Hello, world! ``` 如果你想编写 Python 扩展模块,那么你需要使用 CPython 的 C API。一个简单的示例是使用 CPython 的 C API 来编写一个函数,将两个 Python 整数相加,并返回结果。 ```c // add.c #include <Python.h> static PyObject *add(PyObject *self, PyObject *args) { int a, b; if (!PyArg_ParseTuple(args, "ii", &a, &b)) { return NULL; } return PyLong_FromLong(a + b); } static PyMethodDef methods[] = { {"add", add, METH_VARARGS, "Add two integers."}, {NULL, NULL, 0, NULL} }; static struct PyModuleDef module = { PyModuleDef_HEAD_INIT, "my_module", "My custom module.", -1, methods }; PyMODINIT_FUNC PyInit_my_module(void) { return PyModule_Create(&module); } ``` 你可以使用以下命令将其编译为共享库: ``` $ gcc -shared -o my_module.so add.c $(python3-config --ldflags) ``` 然后,你可以在 Python 中使用它: ```python # main.py import my_module result = my_module.add(1, 2) print(result) ``` 你可以在命令行中使用以下命令来执行 main.py: ``` $ python main.py 3 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值