Workiva Scripting 和对 Python 3.9 的支持已终止
为了确保您的自动化流程能够面向未来, Workiva引入了对Python 3.13 的支持,以及一个脚本级别的设置,允许您为每个脚本选择运行时版本。本指南解释了如何安全地从 3.9 版本升级到 3.13 版本,需要测试哪些内容,以及如何以最小的干扰推出更改。
直到 2025年 10 月, Workiva Scripting 一直依赖于 Python软件基金会发布的官方 Python 3.9 版本;该版本于 2025 年 10 月停止维护,因此不再接收安全更新或错误修复。
为此,Workiva Scripting 已过渡到使用 Amazon Linux 2023 (AL2023) 镜像,该镜像提供自己的构建,并支持 Python 3.9 和 Python 3.13。这一变化确保了 Python 3.9 能够通过亚马逊的更新周期获得持续的安全补丁 和维护,即使上游 Python 版本不再由开源社区进行修补。
由于这一转变,Workiva Scripting 将继续支持在 Python 3.9 上安全地运行脚本 ,直到2027年 10 月。
谁应该考虑这次移民问题?任何目前在 Python 3.9 上运行 Workiva Scripting 自动化脚本的用户——无论是手动触发、通过 Chains 触发还是通过集成自动化触发。
如果我什么都不做呢?您的脚本将通过 AL2023 补丁保持安全,直至 2027 年 10 月,但我们建议您迁移到 Python 3.13,因为它是较新的受支持运行时。
有关生命周期结束时间表和支持版本的更多背景信息,请查看官方的 Python 发布状态网页。
Workiva如何支持这一变革
Workiva推出了一项更新,让开发者可以控制脚本使用的Python运行时环境。本次更新带来了以下变化:
- Python 3.13 支持: 所有新脚本现在默认使用 Python 3.13,这是最新的稳定版本。
- 每个脚本的运行时迁移: 现有的 Python 3.9 脚本可以迁移到 Python 3.13。脚本迁移到 Python 3.13 后,无法再改回 Python 3.9。
- 向后兼容性: 所有现有脚本将继续使用 Python 3.9,直到您更新它们为止。
- 编辑器和 API 支持: 您可以直接在 Workiva 脚本编辑器中或通过脚本 API 设置或更新运行时。
这样可以确保您能够按照自己的时间表进行迁移,安全地进行测试,并且只有在您确信生产脚本准备就绪时才切换它们。
此次转换的时间表
为了方便您规划,以下是推广时间表:
- Workiva 中提供 Python 3.13(2025 年 9 月): 现有的 Python 3.9 脚本可以使用脚本 API 或脚本编辑器迁移到 Python 3.13。新脚本使用 Python 3.13。
- Python 3.9 生命周期结束(2025 年 10 月): Python 官方社区支持结束。Workiva 将继续通过 AL2023 提供支持至 2027 年 10 月,但强烈建议进行迁移。
- 2027 年 10 月: Workiva 计划于 2027 年 10 月停止对 Python 3.9 的支持,之后所有脚本都将在 Python 3.13 上运行。
过渡
你应该尽快开始在 Python 3.13 上测试脚本,同时保持生产环境仅使用 3.9,直到你验证它们在 3.13 上能够正确运行。一旦您能够熟练使用 Python 3.13,请立即将您的生产脚本切换到 Python 3.13 运行时环境。
将脚本切换到 Python 3.13
我们推荐的推广模式:创建副本,更新版本,测试,然后推广。这样可以最大限度地降低生产风险,并允许您在需要时保留运行历史记录。
第一步——制作一份副本
- 在 Workiva 中,复制您的生产脚本。
该副本将设置为 Python 3.13。
步骤二——测试并调整文案
- 在安全/测试环境下运行复制操作。
- 修复所有重大变更(参见“常见问题及修复”)。
- 验证输出、副作用和性能。
步骤 3 — 更改为 3.13(两种选择)
选项 A — 这将保留生产运行历史记录
- 通过复制粘贴,将 副本 中的更新代码推送回 原始 脚本。
- 将 原始 脚本的运行时更改为 Python 3.13。
- 重新运行测试,然后恢复原有的正常调度/触发器。
- (可选)存档或停用副本。
选项 B — 这将不会保留生产运行历史记录
- 将 生产触发器 (即 Chains 触发器)从 原始 脚本指向 复制 脚本。
- 副本 成为新的生产脚本(运行于 Python 3.13)。
- (可选)存档或停用原件。
行动号召: 无论您选择哪个选项,请在 2027 年 10 月之前将所有活动脚本迁移到 Python 3.13 。
更新 Python 运行时版本
使用脚本 API
开始之前,请确保您的 API 授权包含script:read和script:write范围。有关创建或更新 API 授权的说明,请参阅 Workiva API 设置。
-
确定脚本的运行时间。
GET /scripts/{scriptId} Authorization: Bearer {token} X-Version: 2026-01-01检查响应中
runtime的值。 -
将脚本更新至 Python 3.13。
PATCH /scripts/{scriptId} Authorization: Bearer {token} X-Version: 2026-01-01 Content-Type: application/json [{ "op": "replace", "path": "/runtime", "value": "python3.13" }]
更改运行时不会自动重新生成脚本的依赖项包。如果脚本包含 requirements.txtsource,则在更新运行时后启动依赖项生成,并等待操作完成后再运行脚本。没有 requirements.txt 的脚本不需要生成依赖项。
更多详情,请参阅以下 Workiva 开发者页面:
示例:更改和读取 Python 运行时版本
以下示例代码检索脚本的当前运行时,将其迁移到 Python 3.13,并使用脚本 API 重新生成其依赖项包。
import os import time import requests CLIENT_ID = os.environ["CLIENT_ID"] CLIENT_SECRET = os.environ["CLIENT_SECRET"] SCRIPT_ID = os.environ["SCRIPT_ID"] API_VERSION = "2026-01-01" API_BASE_URL = "https://api.app.wdesk.com" SCRIPTS_API_URL = f"{API_BASE_URL}/scripts" AUTH_URL = f"{API_BASE_URL}/oauth2/token" def get_auth_headers(client_id, client_secret): response = requests.post( AUTH_URL, headers={ "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8", "X-Version": API_VERSION, }, data={ "client_id": client_id, "client_secret": client_secret, "grant_type": "client_credentials", }, timeout=30, ) response.raise_for_status() return { "Authorization": f"Bearer {response.json()['access_token']}", "X-Version": API_VERSION, } def read_version(script_id, headers): response = requests.get( f"{SCRIPTS_API_URL}/{script_id}", headers=headers, timeout=30, ) response.raise_for_status() script = response.json() print( f"'{script['name']}' 脚本的 Python 版本: " f"{script['runtime'].replace('python', '')}" ) def change_to_python_313(script_id, headers): response = requests.patch( f"{SCRIPTS_API_URL}/{script_id}", headers={ **headers, "Content-Type": "application/json", }, json=[{ "op": "replace", "path": "/runtime", "value": "python3.13", }], timeout=30, ) response.raise_for_status() script = response.json() print( f"'{script['name']}' 脚本的 Python 版本已更改为: " f"{script['runtime'].replace('python', '')}" ) def has_requirements(script_id, headers): response = requests.get( f"{SCRIPTS_API_URL}/{script_id}/sources", headers=headers, timeout=30, ) response.raise_for_status() return any( source["path"] == "requirements.txt" for source in response.json()["data"] ) def regenerate_dependencies(script_id, headers): response = requests.post( f"{SCRIPTS_API_URL}/{script_id}/dependencies/generation", headers=headers, timeout=30, ) response.raise_for_status() operation_url = response.json()["operationLocation"] while True: operation_response = requests.get( operation_url, headers=headers, timeout=30, ) operation_response.raise_for_status() operation = operation_response.json() if operation["status"] in {"completed", "failed", "cancelled"}: break time.sleep( int(operation_response.headers.get("Retry-After", "5")) ) if operation["status"] != "completed": raise RuntimeError( f"依赖生成结束,状态为 " f"{operation['status']}: {operation}" ) headers = get_auth_headers(CLIENT_ID, CLIENT_SECRET) read_version(SCRIPT_ID, headers) change_to_python_313(SCRIPT_ID, headers) if has_requirements(SCRIPT_ID, headers): regenerate_dependencies(SCRIPT_ID, headers) print("依赖项已成功重新生成。") else: print("未找到 requirements.txt 源文件;已跳过依赖项生成。")使用脚本编辑器
使用脚本编辑器,您可以直接在用户界面中配置运行时。对于使用 Python 3.9 的现有脚本,请使用 属性 → 运行时版本 将其迁移到 Python 3.13。保存后,脚本无法改回 Python 3.9。
在编辑器中更新脚本:
- 在 脚本编辑器中打开脚本。
- 转到右侧的 属性 面板。
- 在 运行时版本下,从下拉列表中选择 Python 3.13 。
- 保存更改。
- 在部署到生产环境之前,请先在安全/测试环境中运行脚本。
使用技巧
- 请确保脚本中的任何第三方软件包都与 Python 3.13 兼容。
- 更新
requirements.txt 文件中所有已固定的软件包版本(例如,与 Python 3.9 不同,requests==2.28在 3.13 中不需要)。 - 请阅读 Python 官方文档,了解有关 Python版本 3.10、3.11、3.12和3.13 的主要变更详情,包括 :
- 结构模式匹配、f字符串更新、改进的错误信息
- 性能显著提升(函数调用、字符串操作、内存管理、JSON 序列化/反序列化)
- 已弃用软件包和某些软件包参数(
例如cgi、cgitb、distutils等已被弃用;asyncio 的“loop”参数已被移除)。
从 3.9 版本迁移到 3.13 版本时常见的迁移问题及解决方法
以下是将脚本从 Python 3.9 迁移到 3.13 时可能遇到的一些常见问题,以及相应的解决方法:
- 第三方库: 某些软件包可能尚不支持 Python 3.13。
- 修复: 升级到最新兼容版本,或替换为替代版本。仔细测试所有已固定的需求。您可以访问 pyreadiness.org/3.13查看您的库是否受支持,并查看“支持的脚本库和依赖项” 帮助文章以获取更多信息。
- requests 库版本:
requests库是 Workiva Scripting 中最常见的第三方库。在 Python 3.9 的早期版本中,脚本会因requests版本 2.30.0 或更高版本而失效。迁移到 Python 3.13 后,即可毫无问题地使用最新版本的requests 。 - Python 3.13 在字符串和字节处理方面有所不同: 更严格的类型检查可能会暴露隐藏的问题。
- 修复: 检查混合使用
str和bytes 的代码,并确保显式编码/解码。
- 修复: 检查混合使用
- 日期时间和时区行为: Python 3.13 在
zoneinfo库和更严格的解析方面有所不同。- 修复: 测试所有日期/时间逻辑,特别是格式和时区转换。
- JSON 序列化: 由于规则更加严格,某些对象可能无法序列化。
- 修复: 确保在
json.dumps之前转换自定义对象,或者使用默认编码器。
- 修复: 确保在
- 已弃用的 API: Python
3.9 中已弃用的某些 Python 标准库 函数(例如,asyncio.get_event_loop、distutils和某些区域设置 API)已被移除。- 修复: 更新代码以使用受支持的替代方案。
- 性能变化: 循环和异步任务的行为可能有所不同。
- 修复: 对关键路径运行负载测试;如有需要,更新并发逻辑。
提示: 务必先测试生产脚本的副本。在受控测试环境中应用修复程序可以降低生产环境出现问题的风险。
Python 3.13 的新特性
以下是Python 3.13的一些主要变化:
- 改进的交互式解释器: 多行编辑、颜色和彩色回溯。
- 实验性自由线程构建模式: 允许在某些平台上使用真正的并行线程(无 GIL)。
- 实验性 JIT: 为性能改进奠定的早期基础。
- 更好的调试工具:
locals()mutations 现在具有明确定义的语义。 - 新的内存分配器: 如果支持,则默认包含并启用修改后的 mimalloc。
- 更小的文件: 文档字符串会去除前导空格,从而减少内存使用和 .pyc 文件大小。
- 新的 dbm 后端: 默认使用
dbm.sqlite3 。 - 平台更新: macOS 最低 10.13,iOS/Android Tier 3,WASI Tier 2。
- 类型改进: 类型默认值、缩小范围、只读项和弃用注释。
- 移除: 已移除已弃用的模块(例如
,cgi、telnetlib、imghdr、lib2to3等)。
有关完整的发行说明,请参阅 Python.org 的“Python 3.13 的新特性”。
如果您想查看 3.9 版本和 3.13 版本之间引入的具体更改,请参阅:
常见问题
问:我需要立即迁移所有脚本吗?
不。现在您可以开始在 Python 3.13 上测试脚本,同时保持生产环境使用 3.9 版本。所有脚本必须在 2027 年 10月之前迁移到 Python 3.13。
问:当 Python 3.9 停止维护时,我现有的脚本是否会自动失效?
不。Workiva Scripting 依赖于 Amazon Linux 2023 (AL2023) 下的 Amazon Python 3.9 版本,该版本将继续获得安全补丁,直至 2027 年 10 月。您的脚本不受 Python 3.9 官方停止维护的影响。
问:我可以在保持生产环境使用 3.9 版本的同时,在 3.13 版本上测试脚本吗?
是的。创建脚本副本以进行测试——该副本会自动设置为在 Python 3.13 上运行。在将文案发布到生产环境之前,请修复文案中的所有问题。为避免失去兼容性,请保留单独的版本——一个用于 3.9,一个用于 3.13——以便在需要时轻松切换。
问:脚本编辑器是否支持更改运行时?
是的。您可以直接在脚本编辑器中设置脚本的 Python 运行时——打开脚本,转到“属性”面板,然后在“运行时版本”下选择版本。
问:我可以在哪里了解更多关于图书馆支持方面的信息?
请查看 pyreadiness.org/3.13 和“支持的脚本库和依赖项” Workiva 帮助文章。
问:如果我切换脚本,我的历史运行数据会发生什么变化?
这取决于。如果覆盖原始脚本,则会保留运行历史记录。如果将触发器指向副本,则原始脚本的运行历史记录将保留在旧脚本中。
问:如果我到 2027 年 10 月仍未迁移,会发生什么?
2027 年 10 月之后,您的脚本将自动过渡到 Python 3.13,届时 Workiva 将停止支持在 AL2023 下运行 Python 3.9 脚本。为避免中断,您应该在 2027 年 10 月之前测试并将脚本迁移到 Python 3.13。
问:迁移时我需要更改我的链或集成自动化吗?
不。只要底层脚本更新到 Python 3.13,您的链式和集成自动化将继续按预期运行。关键步骤是确保脚本本身已迁移。
问:如果出现问题,我可以将脚本从 Python 3.13 回滚到 3.9 吗?
不。一旦脚本设置为 Python 3.13,其运行时就无法切换回 Python 3.9。如果您需要备用方案,请在 Python 3.9 上保留一份单独的脚本副本——维护一个 3.9 版本和一个 3.13 版本——这样,如果在测试过程中出现问题,您可以恢复到 3.9 版本。