day16-Codex开发微信小程序端-前后端联调-根据figma调整布局

今日内容

1 Python代码调用Coze数字人工作流会员问题

# 1 Python代码调用Coze数字人工作
# 2 python调用Coze工作流官方介绍:https://docs.coze.cn/developer_guides_workflow_run#4dd46fdd
	-会员:支持异步调用工作流---》返回execute_id---》后续根据这个id号查询工作流执行结果
    -非会员:不支持异步调用--》同步等返回
    
# 3 会员:
	1 异步执行工作流
    2 每隔10s,查询一次工作流是否执行完成
    	1 每执行完成,过一会再查
        2 执行完成了,取出视频地址
        
# 2 非会员
	1 同步执行工作流
	2 一直等工作流返回结果,返回的结果中有视频地址,取出来即可

image-20260819200845982

image-20260819201840425

1.1 非会员代码

import requests
import json
import time
import os
from typing import Optional, Dict, Any

'''
注意:非会员模式同步调用工作流,可能会因为工作流执行时间过长问题,导致无法获取到真正的数据。建议充值会员,使用会员模式
个人访问令牌:https://www.coze.cn/open/oauth/pats
'''


class CozeAPI:
    """Coze API客户端,用于调用Coze的工作流"""

    def __init__(self, api_key: str = None, workflow_id: str = None):
        self.api_key = api_key or 'pat_FdYI5dz17AqshOrvkTaZsB4nmK9ecQO0WlI9phbTU8qWUKLduWMv41CHyf7yh7yJ'
        self.workflow_id = workflow_id or '7675575485233463305'
        self.base_url = 'https://api.coze.cn'
        self.upload_url = f"{self.base_url}/v1/files/upload"
        self.run_url = f"{self.base_url}/v1/workflow/run"
        self.headers = {'Authorization': f'Bearer {self.api_key}', 'Content-Type': 'application/json'}

    def _get_save_path(self, task_id: str) -> str:
        """内部方法:生成视频保存路径"""
        result_dir = os.path.join('coze_results')
        os.makedirs(result_dir, exist_ok=True)
        filename = f"result_{task_id}_{int(time.time())}.mp4"
        return os.path.join(result_dir, filename)

    def download_video(self, image_url: str, task_id: str) -> Optional[str]:
        """下载视频到本地,返回跨平台路径"""
        try:
            save_path = self._get_save_path(task_id)
            resp = requests.get(image_url, stream=True, timeout=120)
            resp.raise_for_status()

            with open(save_path, 'wb') as f:
                for chunk in resp.iter_content(chunk_size=8192):
                    if chunk:
                        f.write(chunk)

            print(f"视频下载成功: {save_path}")
            return save_path.replace('\\', '/')
        except Exception as e:
            print(f"视频下载失败: {str(e)}")
            return None

    def upload_file(self, file_path: str) -> str:
        """上传文件到Coze并获取文件ID"""
        if not os.path.exists(file_path):
            raise FileNotFoundError(f"文件不存在: {file_path}")

        try:
            print(f"开始上传文件: {file_path}")
            with open(file_path, 'rb') as f:
                files = {'file': (os.path.basename(file_path), f)}
                resp = requests.post(
                    self.upload_url,
                    headers={'Authorization': f'Bearer {self.api_key}'},
                    files=files,
                    timeout=120
                )

            print(f"上传响应: {resp.status_code} | {resp.text}")
            result = resp.json()

            if resp.status_code == 200 and result.get('code') == 0 and 'data' in result:
                file_id = result['data'].get('id')
                if not file_id:
                    raise Exception(f"未提取到文件ID: {result}")
                print(f"文件上传成功,ID: {file_id}")
                return file_id
            raise Exception(f"文件上传失败: {result}")
        except Exception as e:
            print(f"文件上传异常: {str(e)}")
            raise

    def _extract_video_url(self, output_data: Any) -> Optional[str]:
        """从工作流输出中提取视频地址,兼容同步和异步返回结构"""
        try:
            if isinstance(output_data, str) and output_data.startswith(('http://', 'https://')):
                return output_data

            current = output_data
            for _ in range(3):
                if isinstance(current, str):
                    current = json.loads(current)
                    continue
                break

            if not isinstance(current, dict):
                return None

            output_value = current.get('output')
            if isinstance(output_value, str) and output_value.startswith(('http://', 'https://')):
                return output_value

            nested_output = current.get('Output')
            if nested_output is not None:
                nested_url = self._extract_video_url(nested_output)
                if nested_url:
                    return nested_url

            if isinstance(output_value, (dict, str)):
                return self._extract_video_url(output_value)
        except (json.JSONDecodeError, TypeError):
            return None

        return None

    def _parse_run_result(self, result: Dict[str, Any]) -> Dict[str, Any]:
        """解析工作流执行结果,兼容非会员同步和会员异步返回"""
        output_data = result.get('data')
        if output_data:
            video_url = self._extract_video_url(output_data)
            task_id = str(result.get('execute_id') or int(time.time() * 1000))

            if video_url:
                local_path = self.download_video(video_url, task_id)
                return {
                    'code': 0,
                    'msg': 'success',
                    'data': {
                        'status': 'success',
                        'task_id': task_id,
                        'workflow_id': self.workflow_id,
                        'result_video_url': video_url,
                        'local_video_path': local_path,
                        'raw_output': output_data
                    }
                }

            return {
                'code': 0,
                'msg': 'success',
                'data': {
                    'status': 'success',
                    'task_id': task_id,
                    'workflow_id': self.workflow_id,
                    'raw_output': output_data
                }
            }

        task_id = result.get('execute_id')
        if task_id:
            print(f"工作流已异步提交,任务ID: {task_id}")
            return {
                'code': 0,
                'msg': 'success',
                'data': {
                    'status': 'pending',
                    'task_id': task_id,
                    'workflow_id': self.workflow_id
                }
            }

        raise Exception(f"工作流返回中没有 data 或 execute_id: {result}")

    def run_workflow(self, source_image: str, target_image: str, is_async: bool = False) -> Dict[str, Any]:
        """运行Coze数字人工作流;非会员默认同步执行"""
        try:
            source_id, target_id = self.upload_file(source_image), self.upload_file(target_image)

            payload = {
                "workflow_id": self.workflow_id,
                "parameters": {
                    "voice": json.dumps({"file_id": source_id}),
                    "video": json.dumps({"file_id": target_id}),
                    "text": "执行数字人操作"
                },
                "app_id": "",
                "is_async": is_async
            }

            print(f"调用工作流 {self.workflow_id},is_async={is_async}...")
            resp = requests.post(self.run_url, headers=self.headers, json=payload, timeout=300)

            if resp.status_code != 200:
                raise Exception(f"工作流调用失败: {resp.status_code} | {resp.text}")

            result = resp.json()
            if result.get('code') != 0:
                raise Exception(f"工作流调用失败: {result.get('msg')} | {result}")

            return self._parse_run_result(result)
        except Exception as e:
            print(f"工作流调用异常: {str(e)}")
            raise

    def get_workflow_result(self, task_id: str) -> Dict[str, Any]:
        """查询异步工作流执行结果"""
        try:
            print(f"查询任务 {task_id} 结果...")
            query_url = f"{self.base_url}/v1/workflows/{self.workflow_id}/run_histories/{task_id}"
            resp = requests.get(query_url, headers=self.headers, timeout=60)

            if resp.status_code != 200:
                raise Exception(f"查询失败: {resp.status_code} | {resp.text}")

            result = resp.json()
            if result.get('code') != 0:
                raise Exception(f"查询结果失败: {result.get('msg')} | {result}")

            data = result.get('data', [{}])[0]
            exec_status = data.get('execute_status', '')

            if exec_status == 'Success':
                return self._parse_success_result(data, task_id)
            if exec_status == 'Fail':
                return {'status': 'failed', 'error_message': '任务执行失败', 'task_id': task_id}
            return {'status': 'processing', 'task_id': task_id}
        except Exception as e:
            print(f"查询结果异常: {str(e)}")
            raise

    def _parse_success_result(self, data: Dict[str, Any], task_id: str) -> Dict[str, Any]:
        """解析异步任务成功结果"""
        try:
            video_url = self._extract_video_url(data.get('output', '{}'))

            if not video_url:
                return {'status': 'success', 'message': '任务成功但未返回视频', 'task_id': task_id}

            local_path = self.download_video(video_url, task_id)
            return {
                'status': 'success',
                'result_video_url': video_url,
                'local_video_path': local_path,
                'processing_time': data.get('processing_time', 0),
                'task_id': task_id
            }
        except (json.JSONDecodeError, KeyError) as e:
            print(f"解析输出失败: {str(e)}")
            return {'status': 'success', 'message': '任务成功但解析输出失败', 'task_id': task_id}


if __name__ == '__main__':
    try:
        coze_api = CozeAPI()
        voice_path, video_path = './lqz.mp3', './lqz.mp4'
        print("开始测试Coze数字人工作流(非会员同步模式)...")

        run_result = coze_api.run_workflow(voice_path, video_path, is_async=False)
        print(f"工作流执行结果: {run_result}")

        if run_result.get('code') == 0:
            data = run_result['data']
            status_map = {
                'success': f"测试成功!\nURL: {data.get('result_video_url')}\n本地路径: {data.get('local_video_path')}",
                'pending': f"任务已提交,任务ID: {data.get('task_id')}"
            }
            print(status_map.get(data.get('status'), f"未知状态: {data}"))
    except Exception as e:
        print(f"测试失败: {str(e)}", exc_info=True)

1.2 会员代码

import requests
import json
import time
import os
from typing import Optional, Dict, Any
'''
个人访问令牌:https://www.coze.cn/open/oauth/pats
'''

class CozeAPI:
    """Coze API客户端,用于调用Coze工作流"""

    def __init__(self, api_key: str = None, workflow_id: str = None):
        self.api_key = api_key or 'pat_v3bcwP3HOJxuUr7a6VWau4HEbFBMwFNzlHvy6vhQ3URBIaxMBFZOpDBuFUrEYBfE'
        self.workflow_id = workflow_id or '7669850629418647590'
        self.base_url = 'https://api.coze.cn'
        self.upload_url = f"{self.base_url}/v1/files/upload"
        self.run_url = f"{self.base_url}/v1/workflow/run"
        self.headers = {'Authorization': f'Bearer {self.api_key}', 'Content-Type': 'application/json'}

    def _get_save_path(self, task_id: str) -> str:
        """内部方法:生成视频保存路径(精简路径处理逻辑)"""
        result_dir = os.path.join('coze_results')
        os.makedirs(result_dir, exist_ok=True)
        filename = f"result_{task_id}_{int(time.time())}.mp4"
        return os.path.join(result_dir, filename)

    def download_video(self, image_url: str, task_id: str) -> Optional[str]:
        """下载视频到本地,返回跨平台路径"""
        try:
            save_path = self._get_save_path(task_id)
            resp = requests.get(image_url, stream=True)
            resp.raise_for_status()

            with open(save_path, 'wb') as f:
                for chunk in resp.iter_content(chunk_size=8192):
                    f.write(chunk)

            print(f"视频下载成功: {save_path}")
            return save_path.replace('\\', '/')
        except Exception as e:
            print(f"视频下载失败: {str(e)}")
            return None

    def upload_file(self, file_path: str) -> str:
        """上传文件到Coze并获取文件ID"""
        if not os.path.exists(file_path):
            raise FileNotFoundError(f"文件不存在: {file_path}")

        try:
            print(f"开始上传文件: {file_path}")
            with open(file_path, 'rb') as f:
                files = {'file': (os.path.basename(file_path), f)}
                resp = requests.post(self.upload_url, headers={'Authorization': f'Bearer {self.api_key}'}, files=files)

            print(f"上传响应: {resp.status_code} | {resp.text}")
            result = resp.json()

            if resp.status_code == 200 and result.get('code') == 0 and 'data' in result:
                file_id = result['data'].get('id')
                if not file_id:
                    raise Exception(f"未提取到文件ID: {result}")
                print(f"文件上传成功,ID: {file_id}")
                return file_id
            raise Exception(f"文件上传失败: {result}")
        except Exception as e:
            print(f"文件上传异常: {str(e)}")
            raise

    def run_workflow(self, source_image: str, target_image: str) -> Dict[str, Any]:
        """运行Coze换脸工作流,返回任务信息"""
        try:
            # 批量上传文件
            source_id, target_id = self.upload_file(source_image), self.upload_file(target_image)

            payload = {
                "workflow_id": self.workflow_id,
                "parameters": {
                    "voice": json.dumps({"file_id": source_id}),
                    "video": json.dumps({"file_id": target_id}),
                    "text": "执行数字人操作"
                },
                "app_id": "",
                "is_async": True
            }

            print(f"调用工作流 {self.workflow_id}...")
            resp = requests.post(self.run_url, headers=self.headers, json=payload)

            if resp.status_code != 200:
                raise Exception(f"工作流调用失败: {resp.status_code} | {resp.text}")

            result = resp.json()
            if (result.get('code') == 0 or result.get('msg') == '') and (task_id := result.get('execute_id')):
                print(f"工作流调用成功,任务ID: {task_id}")
                return {'code': 0, 'msg': 'success',
                        'data': {'task_id': task_id, 'workflow_id': self.workflow_id, 'status': 'pending'}}

            raise Exception(f"工作流调用失败: {result.get('msg')} | {result}")
        except Exception as e:
            print(f"工作流调用异常: {str(e)}")
            raise

    def get_workflow_result(self, task_id: str) -> Dict[str, Any]:
        """查询工作流执行结果"""
        try:
            print(f"查询任务 {task_id} 结果...")
            # 简化URL拼接(移除模板字符串,直接格式化)
            query_url = f"{self.base_url}/v1/workflows/{self.workflow_id}/run_histories/{task_id}"
            resp = requests.get(query_url, headers=self.headers)

            if resp.status_code != 200:
                raise Exception(f"查询失败: {resp.status_code} | {resp.text}")

            result = resp.json()
            if result.get('code') != 0:
                raise Exception(f"查询结果失败: {result.get('msg')} | {result}")

            # 提取核心数据
            data = result.get('data', [{}])[0]
            exec_status = data.get('execute_status', '')

            if exec_status == 'Success':
                return self._parse_success_result(data, task_id)
            elif exec_status == 'Fail':
                return {'status': 'failed', 'error_message': '任务执行失败', 'task_id': task_id}
            return {'status': 'processing', 'task_id': task_id}

        except Exception as e:
            print(f"查询结果异常: {str(e)}")
            raise

    def _parse_success_result(self, data: Dict[str, Any], task_id: str) -> Dict[str, Any]:
        """内部方法:解析成功的任务结果(拆分复杂的解析逻辑)"""
        try:
            output = json.loads(data.get('output', '{}'))
            result_data = json.loads(output.get('Output', '{}'))
            video_url = result_data.get('output')

            if not video_url:
                return {'status': 'success', 'message': '任务成功但未返回视频', 'task_id': task_id}

            local_path = self.download_video(video_url, task_id)
            return {
                'status': 'success',
                'result_video_url': video_url,
                'local_video_path': local_path,
                'processing_time': data.get('processing_time', 0),
                'task_id': task_id
            }
        except (json.JSONDecodeError, KeyError) as e:
            print(f"解析输出失败: {str(e)}")
            return {'status': 'success', 'message': '任务成功但解析输出失败', 'task_id': task_id}


if __name__ == '__main__':
    try:
        coze_api = CozeAPI()
        voice_path, video_path = './lqz.mp3', './lqz.mp4'
        print("开始测试Coze数字人工作流...")

        # 运行工作流并获取任务ID
        run_result = coze_api.run_workflow(voice_path, video_path)
        print(f"工作流提交结果: {run_result}")

        if run_result.get('code') == 0:
            task_id = run_result['data']['task_id']
            print(f"任务ID: {task_id}")
            time.sleep(120)  # 等待任务处理
            # 查询结果
            result = coze_api.get_workflow_result(task_id)
            print(f"任务结果: {result}")

            # 精简结果判断逻辑
            status_map = {
                'success': f"测试成功!\nURL: {result.get('result_video_url')}\n本地路径: {result.get('local_video_path')}",
                'processing': "任务仍在处理中",
                'failed': f"任务失败: {result.get('error_message')}"
            }
            print(status_map.get(result.get('status'), " 未知状态"))
    except Exception as e:
        print(f" 测试失败: {str(e)}", exc_info=True)

2 Codex开发微信小程序端

# 1 微信小程序端,不是一个空项目,是一个没写完的项目,让Codex继续编写
	-后端是纯从0编写的
    
    
# 2  无论codex从0或不从0开发微信小程序,我们都需要使用【微信开发者工具】,打开查看页面


# 3 使用提示词,让Codex在原来基础上,继续开发出我们的微信小程序
根据项目需求:01-需求分析/项目需求.md 和项目小程序架构文档:03-架构设计/1-项目后端架构文档.md 和UI设计图:02-UI设计 生成口播数字人小程序端代码
要求:
1.我已经创建了小程序:shuziren_front ,你在这个基础上继续编写,无效的文件和文件夹帮我删除。
2.根据需求帮我编写完小程序端代码。
3.接口参考后端项目:shuziren_api ,注意接口返回格式,并正常测试通过,前后端调通。
4.后端链接地址为: http://127.0.0.1:8000 。
5.小程序不使用Skyline 渲染模式。
6.小程序用户未登录,显示登录页面,登录成功进入首页。


# 4 存在问题:
	1 参照的是 html版的 设计图---》只能实现70%效果【我们会解决】
    	-开发完成后,前后端调通了,在根据figma调界面样子
    2 后端没启动,最好是后端启动了,前端一边写,一边测试,bug会少【不大】

3 Codex开发完后端在本地运行

# 1 Codex开发完成,需要运行--》Codex不能运行程序---》使用Pycharm来运行后端
	-Codex:写代码的,前后端都能写
    -Pycharm:运行后端的,能看到样子
    -微信开发者工具:运行微信小程序端,看到样子
    
    
# 2 步骤
	1 使用Pycharm打开后端项目【注意路径】
    2 会自动创建虚拟环境,并安装依赖
    	-坑:依赖中,有一个模块在win上可能装不上【我装上了】--》mysqlclient
        -让Codex解决这个坑
    3 打开Codex,使用提示词把这个坑解决
    	-我在shuziren_api 目录下创建了Python虚拟环境,请帮我把该项目依赖在虚拟环境中安装好
    4 确认数据库mysql已经启动
    5 点击右上角绿色箭头,启动后端项目即可
    6 浏览器中输入:http://127.0.0.1:8000/admin	--》后台管理,给运营用的。我们正常用户都是用小程序
    	-如下图,表示启动好了
    7 登录进后台管理做管理:用户名密码是什么?
    	-有一种可能,在写后端时,Codex顺带创建了超级管理员用户--》输出中会告诉我们用户名密码
        -另一种可能,没创建:使用以下提示词创建
			帮我在后端创建一个超级管理员,用户名:lqz,密码:123456

image-20260819203803227

image-20260819204151433

image-20260819204452592

image-20260819204819585

image-20260819205018963

4 前后端联调-修复bug

# 1 后端写好了,使用Pycharm运行起来了
# 2 前端小程序写好了,使用微信开发者工具在运行呢
# 3 前后端联调--》他们联通,在小程序端测试功能
	-当时在提示词中写了后端地址,已经连好了,我们直接测试功能
    
####################修复bug####################
### 重点:小程序端缓存比较严重,有时候改了代码,用的是缓存,显示的不多--》所以多:清除缓存,重新编译,或者重启####

# 提示词:
# 1 帮我修复小程序端错误:调试器中报红的地方
帮我修复小程序端错误:[ WXSS 文件编译错误] 
ENOENT: no such file or directory, open 'D:/shuziren/shuziren_front/components/navigation-bar/navigation-bar.wxss'(env: Windows,mp,2.01.2510290; lib: 3.17.1)

# 2 测试注册功能
	-帮我修复小程序注册页面:
    	1 用户名能使用中文
        2 目前用户协议同意点不了
        
# 3 上传视频限制在10s内--》去除

# 4 删除视频,实际上删除成功,但是提示删除失败

# 5 首页,点击生成口播,没有反应,无法跳转

# 

image-20260819205449063

4.1 非常重要的问题

##### 小程序端,必须开启 不校验合法域名###
微信小程序只支持https的访问,我们本地运行是http运行
所以打开这个限制---》后续上线必须用htpps部署

image-20260819210903040

5 使用figma-mcp修复界面

# 1 功能测通没问题后,我们要1:1 复原原型图

# 2 官方的:充钱用官方是最好的
	-直接认证
# 3 第三方的:读资源操作--》复原度最好
	-使用apikey
######## 同学们都可以用,有频次限制##########
# 4 突破频次限制的【毕竟不是官方,是第三方,后续可能面临不稳定】

########### 步骤############
# 1 访问地址:https://github.com/gethopp/figma-mcp-bridge
	-原理是:需要有Codex + 桌面端的figma==》使用桌面figma和codex直接通讯,不走网络请求,不受频次限制
    
    
# 2 工作一:在figma桌面端装一个插件
	Download the plugin from the latest release page, then in Figma go to Plugins > Development > Import plugin from manifest and select the manifest.json file from the plugin/ folder

# 3 工作二:在Codex中配置mcp
帮我配置下面的mcp
{
  "figma-bridge": {
    "command": "npx",
    "args": ["-y", "@gethopp/figma-mcp-bridge"]
  }
}


# 4 测试:帮我测试一下 figma-bridge mcp是否可用

image-20260819214551850

image-20260819214649805

image-20260819214826249

image-20260819215010454

image-20260819215035799

image-20260819215204440

5.1 提示词修改小程序界面

使用figma-bridge MCP读取下面Figma画板链接,根据画板内容,帮我修改注册页面布局 (只生成我给你的页面),小程序项目在:shuziren_front
Figma链接:https://www.figma.com/design/RapGbUR0HY8EMSrdD4kJy4/Untitled?node-id=2-49&t=phzC9uE8jirjCobZ-4
约束:
1.输出完整4个文件:wxml / wxss / js / json;
2.全部rpx单位,Figma中1px=2rpx,禁止px;
3.优先flex布局,尽量消除position:absolute;必须定位才保留;
4.图标输出SVG,路径统一写 "/assets/icons/xxx.svg";照片、复杂插画输出PNG‑2x,路径/assets/images/xxx.png;
5.禁止使用Figma临时http图片链接,输出图片导出清单;小程序svg全部用image组件引入,不要把svg源码写进wxml;
6.只修改UI骨架,业务接口逻辑保持不变;bindtap点击事件空占位;
7.适配底部safe‑area‑inset‑bottom安全区;
8.wxss抽class,不引入第三方UI组件库;
9.输出完成列出人工修复风险清单。

image-20260819215512463

6 使用图片修复界面

# 1 从figma中复制出一张图片
# 2 使用codex修改页面
# 3 提示词:
参照这张图片,帮我修改小程序端登录页面的布局

image-20260819220425375

7 购买云服务器【下次课讲完后,你们再操作】

# 1 购买服务器之前学过
# 2 根据上线架构图:要装的软件
	1 Python解释器
    2 Nginx
    3 mysql
    4 uwsgi
    5 上传代码
    6 运行代码,配置nginx转发
    #################### 后端就上线完成#################

7.1 上线架构图

image-20260819221419322

7.2 购买

# 1 阿里云服务器:大家可以买腾讯,华为。。。
https://ecs.console.aliyun.com/server/-/detail?regionId=cn-hangzhou
# 2 选择配置购买

# 3 购买后
	ip:47.111.227.106
    用户名:root
    密码:刚刚设置的
    
# 4 远程连接
	win---》通过软件Finallshell--》连接到购买的linux服务器
    mac---》通过软件Finallshell--》连接到购买的linux服务器

8 安装python3.13

# 0 补充:
	默认centos的操作系统中,有 3.9.25的环境--》因为linux上很多软件是基于python写的--》必须有python解释器环境---》wget 下载文件的软件--》基于python写的
	我们的项目跑在python3.13上
    由此:等我们python3.13装完后:centos9机器上,有两个python解释器环境
    python---》python3.9.25---》pip---》是跟python3.9.25配对的
    python、pip   是 3.9.25
    
    python3.13---》python3.13--》pip3.13--》装第三方软件的
    python3.13、pip3.13 是我们自己装的
    

    
#1  源码安装python,依赖一些第三方zlib* libffi-devel
dnf install openssl-devel bzip2-devel expat-devel readline-devel sqlite-devel psmisc libffi-devel zlib* libffi-devel  -y

# 2 前往用户根目录
cd 

#2 下载  3.13.11 源码 服务器终端
# https://registry.npmmirror.com/binary.html?path=python/
wget https://registry.npmmirror.com/-/binary/python/3.13.11/Python-3.13.11.tgz # 阿里云提供的
# wget https://www.python.org/ftp/python/3.13.11/Python-3.13.11.tgz  # 官方的,国外,慢
    

#3  解压安装包
tar -xf Python-3.13.11.tgz

#4 进入目标文件
cd Python-3.13.11

#5  配置安装路径:/usr/local/python3
# 把3.13.11 编译安装到/usr/local/python311路径下
./configure --prefix=/usr/local/python313

#6  编译并安装,如果报错,说明缺依赖
# yum install openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel psmisc libffi-devel zlib* libffi-devel  -y
# make只是编译----》可执行文件,没有安装
# 类似于在win上下载了安装包,但是没安装
# make install 安装---》类似于在win上下了安装包,一路下一步安装了,指定安装位置---》/usr/local/python3
make &&  make install

# 7  建立软连接:/usr/local/python313路径不在环境变量,终端命令 python3,pip3
ln -s /usr/local/python313/bin/python3 /usr/bin/python3.13
ln -s /usr/local/python313/bin/pip3 /usr/bin/pip3.13

# 机器上有多个python和pip命令,对应关系如下
python       3.9      pip 
python3.13   3.13     pip3.13

#8  删除安装包与文件:[可以留着不删]
rm -rf /root/Python-3.13.1
rm -rf /root/Python-3.13.11.tgz
# 1 Python代码调用Coze数字人工作流会员问题
# 2 Codex开发完后端在本地运行
# 3 Codex开发微信小程序端
# 4 前后端联调-修复bug
# 5 使用figma-mcp修复界面
# 6 使用图片修复界面
# 7 购买云服务器
# 8 安装python3.13
# 9 安装nginx
# 10 安装mysql
posted @ 2026-08-23 09:40  凫弥  阅读(6)  评论(0)    收藏  举报