iOS 项目中如何使用 Python
我所在的公司对项目编译后的大小和资源文件有严格的要求,每次集成发版对于包体积的增量都是有严格的控制,因此,如何减少包体积是每一个研发都需要考虑的。
对于包体积大小我们可以从资源文件和编码来控制,如何减少项目编译文件的大小,只能从代码层面去进行一些优化,如规范代码,合理的使用组合、继承等设计模式。对于资源文件,如图片我们可以进行压缩后在集成。下面就是如何利用python对项目中的使用的图片进行检测并实现在线压缩、上传等功能。
正确引入 Python
Python 库本身就支持 C 直接调用,只要我们能正确的引入即可。git上查找了下,果然已经有人给我们造好了轮子点这个链接,作者已经把对应版本 python 压缩成 zip 并上传,可直接下载解压使用,当然我们也可以使用提供的 makefile 脚本自行编译。同时作者还提供了一个快速创建iOS项目的模版点这个链接以下是记录使用过程中的一些问题。
模版项目的安装
下载作者提供的模版项目到本地点这个链接,查看作者提供的README.rst 文件,两个步骤快速生成模版项目(我是使用自己手动创建的项目)
step1 执行 $ pip install cookiecutter 安装 cookiecutter 插件
step2 执行 $ cookiecutter https://github.com/pybee/Python-iOS-template --checkout 3.7 安装指定版本的python
生成的项目的整体目录结构如下所示
0.png
3.8 版本 \'cpython/initconfig.h\' file not found 错误
目前最新的Python版本已经是3.8了,本着使用最新版本的原则,下载了3.8版本,解压后引入工程,
编译项目出现如下错误:
1.png
通过错误提示和头部标识,我们发现这个文件不能直接被引用使用,在看下所有的 cpython 目录下文件,除了initconfig.h 文件其他都有 this header file must not be included directly 标识,既然不能直接 included 直接干掉整个 cpython 目录除 initconfig.h 的所有文件。再次编译发现错误如下
2.png
在查看python headers 目录下的所有文件,发现还有外层还有一个 pystate.h 文件,里面有一个对 cpython 目录除 pystate.h 引用,但是刚刚已经被我们删了
3.png
删除也无法解决问题,说明该方式不对。查看了下issues里面的问题列表,也没有发现该问题和解决方法,既然高版本不行,只能使用3.7了。
3.7 版本
替换项目中的python相关文件,直接编译项目这次更离谱22个错误
4.png
查看错误会发现这些报错都是Python目录的 Resource/lib 文件下的文件,直接把该文件目录删除再次运行项目,这次运行成功了。完整的项目截图如下所示
5.png
ps记得引入 libz.tdb 和 libsqlite3.tdb 两个模块。
代码尝试 No module named \'encodings\' 错误
直接将模版项目中main文件的代码粘贴复制到自己项目中,运行项目这次出现了如下错误
6.png
错误是越来越多了,分析下错误提示发现是sqlite3库问题,检查下项目中如下的配置位置,发现是libz.tdb 和 libsqlite3.tdb 两个模块没有被导入,按下图正确导入
7.png
再次运行项目,项目运行起来,但是新的错误又出现了
8.png
python在初始化的时候失败了没有找到 encodings 模块,想到前面删除的 Resource/lib 文件目录,那么还是我们对模块引入的方式有问题,从网上找了下 iOS 工程中调用Python方法,看到这篇文章有关于Home路径的设置,下载了作者提供的代码,发现可以把该模块制作成 bundle模块引入项目,并修改原代码中关于 python_home 项目终于正确的运行起来了,修改删除无用的代码,并创建测试 main.py 文件,控制台成功打印出日志
9.png
完整的 main.m 代码
#import "AppDelegate.h"#import "Python.h"
#include <dlfcn.h>
int main(int argc, char *argv[]) {
int ret = 0;
unsigned int I;
NSString *tmp_path;
NSString *python_home;
NSString *python_path;
wchar_t *wpython_home;
const char* nslog_script;
const char* main_script;
wchar_t** python_argv;
@autoreleasepool {
NSString * resourcePath = [[NSBundle mainBundle] resourcePath];
// Special environment to prefer .pyo; also, don\'t write bytecode
// because the process will not have write permissions on the device.
putenv("PYTHONOPTIMIZE=1");
putenv("PYTHONDONTWRITEBYTECODE=1");
putenv("PYTHONUNBUFFERED=1");
// Set the home for the Python interpreter
python_home = [NSString stringWithFormat:@"%@/PythonEnv.bundle/Resources", resourcePath, nil];
NSLog(@"PythonHome is: %@", python_home);
wpython_home = Py_DecodeLocale([python_home UTF8String], NULL);
Py_SetPythonHome(wpython_home);
// Set the PYTHONPATH
python_path = [NSString stringWithFormat:@"PYTHONPATH=%@/Library/Application Support/com.example.jddd/app:%@/Library/Application Support/com.example.jddd/app_packages", resourcePath, resourcePath, nil];
NSLog(@"PYTHONPATH is: %@", python_path);
putenv((char *)[python_path UTF8String]);
// iOS provides a specific directory for temp files.
tmp_path = [NSString stringWithFormat:@"TMP=%@/tmp", resourcePath, nil];
putenv((char *)[tmp_path UTF8String]);
NSLog(@"Initializing Python runtime...");
Py_Initialize();
main_script = [
[[NSBundle mainBundle] pathForResource:@"main"
ofType:@"py"] cStringUsingEncoding:NSUTF8StringEncoding];
if (main_script == NULL) {
NSLog(@"Unable to locate jddd main module file.");
exit(-1);
}
// If other modules are using threads, we need to initialize them.
PyEval_InitThreads();
@try {
// Start the main.py script
NSLog(@"Running \'%s\'...", main_script);
FILE* fd = fopen(main_script, "r");
if (fd == NULL) {
ret = 1;
NSLog(@"Unable to open \'%s\'; abort.", main_script);
} else {
ret = PyRun_SimpleFileEx(fd, main_script, 1);
fclose(fd);
if (ret != 0) {
NSLog(@"Application quit abnormally!");
} else {
// In a normal iOS application, the following line is what
// actually runs the application. It requires that the
// Objective-C runtime environment has a class named
// "PythonAppDelegate". This project doesn\'t define
// one, because Objective-C bridging isn\'t something
// Python does out of the box. You\'ll need to use
// a library like Rubicon-ObjC [1], Pyobjus [2] or
// PyObjC [3] if you want to run an *actual* iOS app.
// [1] http://pybee.org/rubicon
// [2] http://pyobjus.readthedocs.org/
// [3] https://pythonhosted.org/pyobjc/
UIApplicationMain(argc, argv, nil, @"PythonAppDelegate");
}
}
}
@catch (NSException *exception) {
NSLog(@"Python runtime error: %@", [exception reason]);
}
@finally {
Py_Finalize();
}
NSLog(@"Leaving...");
}
exit(ret);
return ret;
}
在学习Python的过程中,往往因为没有资料或者没人指导从而导致自己不想学,可以看我主页哦 ,配套资料、python、pycharm安装包可以都有,不管是学习到哪个阶段的小伙伴都可以获取到自己相对应的资料,感谢支持!!!
以上是 iOS 项目中如何使用 Python 的全部内容, 来源链接: utcz.com/z/389340.html