当前位置: 首页 > news >正文

税务门户网站建设方案国际局势最新消息今天

税务门户网站建设方案,国际局势最新消息今天,北海网站建设服务商,wordpress调用指定分类名称链接目录 背景Python程序的「加密」什么是CythonCython用法之setup脚本安装Cython编译前编译后结论 Cython用法之cythonize命令Cython编译引入的类型转换问题问题描述排查思路解决方案反思 背景 近一年来在Python方面做了不少事情:最早接触Python是利用selenium写了一个…

目录

  • 背景
  • Python程序的「加密」
  • 什么是Cython
  • Cython用法之setup脚本
    • 安装Cython
    • 编译前
    • 编译后
    • 结论
  • Cython用法之cythonize命令
  • Cython编译引入的类型转换问题
    • 问题描述
    • 排查思路
    • 解决方案
    • 反思

背景

近一年来在Python方面做了不少事情:最早接触Python是利用selenium写了一个网页爬虫。2024年上半年利用scikit-learn做了机器学习方面的入门实践;下半年开始接触UE5、Blender等3D建模、视觉相关工具的脚本开发,这些工具都提供Python的开发接口。通过Python学到了不少新知识,感触最深的就是,Python太方便了。有太多太多的库可以被集成调用,几乎除了业务逻辑,技术实现都可以是拿来主义。

因为之前更多的是项目管理,好久没有发coding的博文了,最近准备把关于Python的相关实践总结下,分一篇或多篇博文记录,主要记录实现方案、遇到的问题和解决思路。
涉及的话题如下,想道哪写到哪。

  1. UE引擎的Python脚本开发,实现批量全自动的渲染队列,并加入通知报警等功能。关键词:UE、ndisplay、渲染队列。
  2. Blender的Python脚本开发,实现自定义的模型生成。关键词:obj文件类型、uv展开、用shapely对二维几何图形的计算、rectpack二维矩形打包问题、pillow图像生成。
  3. Python程序的打包。关键词:PyInstaller、Conda
  4. Python程序的「加密」。关键词:Cython
  5. 更早前的,Python机器学习包。关键词:scikit-learn、pandas、numpy
  6. 更早前的,Python实现的网页爬虫。关键词:selenium

Python程序的「加密」

我们的Python程序是随着客户端一同发布的,为了防止Python源码泄漏,我们通过Cython对核心代码编译后再进行打包发布,以提高窃取/破解的难度或门槛。

什么是Cython

Cython可以将Python程序转化为C/C++语言,并编译为动态库文件(在Windows上为.pyd,在Mac/Linux上为.so),可以支持与C/C++库的调用,可以进一步加速Python程序。因此,Cython本质目的其实并不是做加密,只是经过编译后的Python程序的破解提高了一个难度。

Cython 3.0 中文文档

Cython用法之setup脚本

安装Cython

pip install Cython

编译前

一个简单的例子,目录结构如下:

.
├── hello.py
├── lib
│   └── utils.py
├── main.py
└── setup.py

main.py是主程序,导入了一个hello模块

# main.py
from hello import sayhellosayhello('Kw')

hello.py也引用了一个/lib/utils.py,用于测试Cython是否会自动检索引用关系并编译引用模块,以及测试编译结果的输出目录结构。

# hello.py
from lib.utils import saywelcomedef sayhello(name):print(f'hello {name}')saywelcome(name)

/lib/utils.py

# /lib/utils.py
def saywelcome(name):print(f'welcome {name}')

setup.py是Cython执行脚本,指定了要编译的hello.py以及lib/utils.py

# setup.py
from distutils.core import setup
from Cython.Build import cythonizesetup(ext_modules = cythonize(["hello.py","lib/utils.py",]), 
)

main.py是入口文件,需要被python解释器调用,因此入口文件是不进行编译的。核心代码应该模块化。

运行setup.py执行编译;其中--inplace令生成的编译文件在当前目录位置:

python3 setup.py build_ext --inplace

编译后

编译完成后的目录结构:

.
├── hello.c
├── hello.cpython-311-darwin.so
├── hello.py
├── lib
│   ├── utils.c
│   └── utils.py
├── main.py
├── setup.py
└── utils.cpython-311-darwin.so

可以看到,在需编译的.py文件同级目录处生成了同名的.c文件,但所有编译后的.so文件均位于构建脚本执行目录,而非源文件所在处。如,utils.xxx.so并没有直接生成在/lib目录下。

为了验证main.py可以正确使用.so以代替.py文件,删除无关的.c/.py文件,并将utils.so移动至/lib下,目录结构如下:

.
├── hello.cpython-311-darwin.so
├── lib
│   └── utils.cpython-311-darwin.so
└── main.py

utils.cpython-311-darwin.so 命名中「cpython-311-darwin」部分无需调整。

执行主程序:python3 main.py,正确输出:

hello Kw
welcome Kw

结论

  1. Cython不会自动检索Python代码的包引用关系,需显示指定每个待编译.py文件。
  2. 输出的.so/.pyd文件不会保持原有目录结构,需自行处理。
  3. 基于结论1和2,需要编写脚本自动编译项目下的所有.py,并保持目录结构。一个思路是先复制整个项目目录文件,用内联的方式在对应位置编译.so/.pyd,以保留目录结构(保留引用关系),最后再删除无用.py/.c(防止源码泄漏)。

Cython用法之cythonize命令

适用于编译单个.py,生成.so。

cythonize -i hello.py

由于前文关于「Cython的结论3」,可以利用该命令编写一个脚本,实现保持工程目录结构的自动编译。见[TODO,还没写]

Cython编译引入的类型转换问题

这个问题其实是撰写本文的初衷

在编译实际Python项目时遇到一个问题:一个模块方法在编译前(.py)源码可以执行,但在编译后(.so)执行异常。提示TypeError: Expected list, got numpy.ndarray

问题描述

问题简化描述为:
/lib/utils.py里有一个将list转化为numpy数组的方法:

# /lib/utils.py
import numpy as npdef list2ndarray(vertices: list):vertices = np.array(vertices) # 为何不直接 return np.array(vertices)? # 因为此处是简化的代码,转化后的vertices在实际项目中有其他使用。return vertices

main.py中调用时,顺利执行;

# main.py
from lib.utils import list2ndarraya = list2ndarray([4,5,6])
print(f'{type(a)}, {a}')  # 输出 <class 'numpy.ndarray'>, [4 5 6]

但将(utils.py)编译为utils.so后,执行异常。错误定位在utils.py的这一行代码:

def list2ndarray(vertices: list):vertices = np.array(vertices)  # 这一行抛出错误 TypeError: Expected list, got numpy.ndarrayreturn vertices

排查思路

  1. 一开始排查方向是numpy的类型转化,通过搜索引擎以及AI查询TypeError: Expected list, got numpy.ndarray相关错误,引导了几个方向:numpy版本问题、输入参数类型问题等。
  2. 通过调试确认输入参数在编译前后没有变化,明确是list类型。代码是在编译后发生异常,可以确认是Cython引入的问题。
  3. 多番尝试(花了一上午),确认是Cython与Python在隐式转换方面的不同导致的。

原因具体是:
def list2ndarray(vertices: list):声明了vertices是list类型,在传入np.array(vertices)后是可以被正确转化的,但返回值是ndarray类型;此时在将该返回值(ndarray类型)赋值给vertices变量(声明为list类型)时,Python完成了隐式转换,而Cython环境下认为非法TypeError: Expected list, got numpy.ndarray:因为对于vertices变量而言,它预期接收list,但却被给予了ndarray。

问题代码换一种写法的话,会使得该问题更清晰:

def list2ndarray(list_value: list): # list_value 是 list类型ndarray_value = np.array(list_value) # ndarray_value 是 ndarray类型list_value = ndarray_value # Cython下,无法将ndarray_value隐式转化为list_value,因此抛出异常return list_value

进一步查询相关资料,得到确认:

Cython的类型声明严格性,而纯Python代码具有动态类型特性,允许隐式转换。

解决方案

确认问题后,解决方案就简单了。
第一种:不声明入参类型,允许隐式转换;但此举难免有点“暧昧不亲”。

def list2ndarray(vertices: list):  # 改为
def list2ndarray(vertices): # 不声明list类型

第二种:避免所谓的“动态类型”,使用正确类型的变量:

def list2ndarray(list_value: list):ndarray_value = np.array(list_value)# list_value = ndarray_value # 避免所谓的“动态类型”return ndarray_value # 使用正确的变量

问题得解。

反思

其实,这个问题就是一个馒头引发的血案,花了一个早上时间排查,值得记录一下。
在Python或JS这类「弱类型、支持动态类型」的编程环境中,没有了类型的束缚,代码写起来非常自由自在,我也很喜欢这种感觉。但是,这就要求Coder对数据的流转了然于心,否则这种小问题很隐晦,可能需要排查半天。反观Java等强类型编程语言里,这种错误编译器都直接提醒你了。

另外,AI确实能提供解决思路,但具体解决方案还是要看人。如果我没有同时做过Java/JS/Python的开发,在这个问题上AI的回答可能让人云里雾里。

http://www.cadmedia.cn/news/1980.html

相关文章:

  • 在建设厅网站怎么办建造师延期网站上不去首页seo要怎么办
  • 注册网站填写不了地区搜狗收录提交
  • 艾臣网站建设网络营销策划方案ppt
  • 网站内做全文搜索注册网站需要多少钱?
  • 建设银行义乌分行网站seo公司排行
  • 网站建设中 gif福州短视频seo平台
  • 即墨网站建设招聘视频优化是什么意思
  • 网站建设是永久性的吗永久免费客服系统软件
  • 酒店网站的建设方案足球世界排名前十
  • 庆阳网站设计 贝壳下拉长沙网站关键词排名公司
  • 没有限制的国外搜索引擎重庆seo排名优化
  • 今天国际新闻最新消息厦门seo小谢
  • 电商网站建设与管理自考试卷yandex搜索引擎
  • 建设公司网站的内容公司搭建网站
  • 郑州最好的品牌策划公司网站排名优化培训电话
  • 深圳网站建设php网站 软件
  • flash做游戏下载网站百度搜索广告投放
  • 安徽建站之星抖音seo搜索引擎优化
  • 万网 网站建设合同市场营销培训课程
  • 常见的网络广告形式seo快速排名网站优化
  • 独立商城系统网站建设等服务重庆人社培训网
  • 建设工程教育网 官网宁波网站推广网站优化
  • 网站的建设与运营专业希爱力的功效及副作用
  • 抖音代运营平台哪个好seo关键词优化如何
  • 学校网站设计实验报告制作一个简单的网站
  • 网站建设项目验收单网上销售推广方案
  • 陕西交通建设集团公司网站网站快速优化排名官网
  • 代理做网站怎么样实时新闻最新消息
  • 西直门网站建设公司十大基本营销方式
  • 巩义便宜网站建设推广网站seo