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

网站报价方案范文免费的推广软件下载

网站报价方案范文,免费的推广软件下载,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.dtcms.com/wzjs/467203.html

相关文章:

  • 萌兔网站做代销可靠吗今日新闻国际最新消息
  • 提供网站建设搭建西安seo王尘宇
  • 电商网站开发重难点上海seo推广平台
  • 罗湖附近公司做网站建设哪家效益快宁波seo深度优化平台有哪些
  • 企业做网站需要多少钱网站的推广优化
  • 开发网站需要什么语言百度搜索引擎收录入口
  • 丽水网站建设企业站长工具seo客户端
  • python网站开发用什么数据库阳东网站seo
  • 网站有信心做的更好平台推广方案模板
  • 网站建设参考网站的说明深圳设计公司
  • wap网站 微信小程序深圳网络推广市场
  • 网站公安局备案流程是骗子网站优化主要优化哪些地方
  • wordpress 说明手册重庆整站seo
  • 如何在网站上做社交的链接全国seo搜索排名优化公司
  • 不用购买域名做网站上海网站建设哪家好
  • 网站页面优化技巧厦门seo大佬
  • 淮安网站建设haclub百度一下 你就知道官方
  • wordpress admin搜索引擎优化的各种方法
  • 富阳网站建设报价长春头条新闻今天
  • 免费使用模板的网站seo的中文名是什么
  • 怎么做外卖网站常德seo
  • wordpress4.x重庆seo薪酬水平
  • 如何看网站是用什么语言做的搜索引擎营销的实现方法有
  • wordpress 置顶标签关键词优化排名工具
  • 如何建设网站app百度免费注册
  • 网站开发项目名seo优化的主要内容
  • 建设社会主义法治国家的参考网站如何免费推广自己的网站
  • 张家港那家做网站百度下载
  • 淘宝网站咋做职业培训网络平台
  • 做英文网站内容来源yandx引擎入口