- 物联网
- 后端
【免费下载链接】OctoPrint
OctoPrint is the snappy web interface for your 3D printer!
OctoPrint 2.0.0 正式移除了过去十年间累积的大量兼容层,长期忽略弃用警告的插件将面临 API 断裂。本文以官方迁移文档为主体,结合仓库源码逐一梳理服务端、客户端、API 与项目组织层面的全部破坏性变更,为插件作者提供可直接对照执行的重命名清单、替换代码与配置映射表。
读完本文你将掌握:如何把octoprint.access.users的旧式 camelCase 方法批量替换为 snake_case 新 API、如何应对BlueprintPlugin端点自动纳入 CSRF 防护、如何迁移serial.*配置块与 blocklist 命名、如何配合新版终端日志前缀(<<</>>>)更新过滤器正则,以及为何现在正是把插件构建迁移到pyproject.toml的最佳时机。
写在最前:这份清单看起来很长,但别被吓到
官方迁移文档开篇就强调:这份清单罗列了 2.0.0 中所有可能需要插件(或客户端)做出调整的变更,但绝大多数插件只需改动一两处,有些甚至完全不需要改动。是否受影响,高度取决于你插件的实现方式与复杂度。
即便如此,即便你的插件不受任何破坏性变更影响,也请务必阅读两节内容:
- 迁移插件到 pyproject.toml 与构建隔离
- 当前已存在弃用警告的即将移除项清单
本文接下来按"服务端 → 客户端 → API → 项目组织"的顺序,完整覆盖官方文档全部条目,并给出仓库源码级的佐证。
服务端变更
访问控制(Access control)
octoprint.access.users.*的方法重命名
octoprint.access.users模块中的UserManager、FilebasedUserManager、User与SessionUser移除了大量长期弃用(且已有替代品)的方法。以 src/octoprint/access/users.py 中的实际定义为准,迁移后的新方法名如下:
octoprint.access.users.UserManager(源码见 src/octoprint/access/users.py#L44):
| 旧方法 | 新方法 |
|---|---|
checkPassword | check_password |
addUser | add_user |
changeUserActivation | change_user_activation |
changeUserPassword | change_user_password |
getUserSetting | get_user_setting |
getAllUserSettings | get_all_user_settings |
changeUserSetting | change_user_setting |
changeUserSettings | change_user_settings |
removeUser | remove_user |
findUser | find_user |
getAllUsers | get_all_users |
hasBeenCustomized | has_been_customized |
changeUserRoles | change_user_permissions |
addRolesToUser | add_permissions_to_user |
removeRolesFromUser | remove_permissions_from_user |
octoprint.access.users.FilebasedUserManager(源码见 src/octoprint/access/users.py#L408):
| 旧方法 | 新方法 |
|---|---|
generateApiKey | generate_api_key |
deleteApiKey | delete_api_key |
addUser | add_user |
changeUserActivation | change_user_activation |
changeUserPassword | change_user_password |
getUserSetting | get_user_setting |
getAllUserSettings | get_all_user_settings |
changeUserSetting | change_user_setting |
changeUserSettings | change_user_settings |
removeUser | remove_user |
findUser | find_user |
getAllUsers | get_all_users |
hasBeenCustomized | has_been_customized |
octoprint.access.users.User(源码见 src/octoprint/access/users.py#L919):
| 旧成员 | 新用法 |
|---|---|
asDict | as_dict |
is_admin/is_user/roles | 改为检查具体权限(见下方示例) |
其中is_admin、is_user这类基于角色字符串的判断,官方推荐改用权限系统(Permissions定义在 src/octoprint/access/permissions.py#L270):
from octoprint.access.permissions import Permissions # instead of user.is_admin: is_admin = user.has_permission(Permissions.ADMIN) # preferred! is_admin = "admin" in user.groups # instead of user.is_user: is_user = not user.is_anonymous # preferred! is_user = "user" in user.groupsoctoprint.access.users.SessionUser(源码见 src/octoprint/access/users.py#L1172):
| 旧成员 | 新成员 |
|---|---|
get_session | session |
octoprint.users模块被移除
octoprint.users已长期弃用,2.0.0 中正式删除。请将导入改为octoprint.access.users:
# old from octoprint.users import UserManager # new from octoprint.access.users import UserManageroctoprint.server.admin_permission与octoprint.server.user_permission被移除
这两个权限辅助对象同样在 2.0.0 被移除。官方给出的"即插即用"替代方案是使用基于组的权限对象:
from octoprint.access import groups admin_permission = groups.GroupPermission(groups.ADMIN_GROUP) user_permission = groups.GroupPermission(groups.USER_GROUP)不过官方强烈建议进一步思考:针对你的具体用例,是否更适合使用更细粒度(甚至自定义权限)的权限方案。ADMIN_GROUP/USER_GROUP的定义位于 src/octoprint/access/groups.py。
文件存储与可打印文件
octoprint.filemanager.FileDestinations.SDCARD的值改变
FileDestinations.SDCARD的枚举值从printer改为sdcard。任何与硬编码字符串"printer"比较的插件都会失效。查看源码 src/octoprint/filemanager/destinations.py 可确认现状:
class FileDestinations: LOCAL = "local" PRINTER = "printer" # for reasons of backwards compatibility SDCARD = PRINTER注意:源码中SDCARD = PRINTER(值仍为"printer")是向后兼容的过渡写法,而 2.0.0 官方文档明确宣布该枚举值已变为sdcard。迁移时应改用FileDestinations.PRINTER做所有必要的判断:
from octoprint.storage import FileDestinations if storage == FileDestinations.PRINTER: # preferred! # do something if storage == FileDestinations.SDCARD: # do somethingUpdatedFiles事件不再携带gcode文件类型
存储子系统产生的UpdatedFiles事件 不再针对文件类型gcode触发,而只针对printables触发。如果你仍依赖type: gcode的UpdatedFiles事件,需要切换到type: printables。
插件系统
BlueprintPlugin端点自动纳入 CSRF 防护
从 OctoPrint 2.0.0 起(自 1.8.3 起预告),通过BlueprintPluginmixin 提供的端点会自动落入 OctoPrint 的 CSRF 防护 范围。相关实现位于 src/octoprint/server/util/csrf.py。
如果这导致你的插件出问题,可以通过@octoprint.plugin.BlueprintPlugin.csrf_exempt装饰器豁免单个端点:
class MyPlugin(octoprint.plugin.BlueprintPlugin): @octoprint.plugin.BlueprintPlugin.route("/hello_world", methods=["GET"]) def hello_world(self): # This is a GET request and thus not subject to CSRF protection return "Hello world!" @octoprint.plugin.BlueprintPlugin.route("/hello_you", methods=["POST"]) def hello_you(self): # This is a POST request and thus subject to CSRF protection. It is not exempt. return "Hello you!" @octoprint.plugin.BlueprintPlugin.route("/hello_me", methods=["POST"]) @octoprint.plugin.BlueprintPlugin.csrf_exempt() def hello_me(self): # This is a POST request and thus subject to CSRF protection, but this one is exempt. return "Hello me!" def is_blueprint_csrf_protected(self): return True要点:
GET请求天然不受 CSRF 保护约束;POST等写请求默认受保护;- 需要豁免的端点用
csrf_exempt()装饰; is_blueprint_csrf_protected返回值控制整组端点是否启用 CSRF 保护。
PluginSettings.get_plugin_data_folder被移除
长期弃用的octoprint.plugin.PluginSettings.get_plugin_data_folder已被删除,取而代之的是octoprint.plugin.OctoPrintPlugin.get_plugin_data_folder。
实操上,把self._settings.get_plugin_data_folder替换为self.get_plugin_data_folder。注意源码实现(src/octoprint/plugin/types.py#L108-L123)会在返回前os.makedirs确保目录存在:
def get_plugin_data_folder(self): if self._data_folder is None: raise RuntimeError( "self._plugin_data_folder is None, has the plugin been initialized yet?" ) import os os.makedirs(self._data_folder, exist_ok=True) return self._data_folder仓库内的内置插件(如 announcements、pluginmanager、softwareupdate、appkeys 等)均已改用self.get_plugin_data_folder()访问各自数据目录(见 src/octoprint/plugins/announcements/init.py#L591、src/octoprint/plugins/softwareupdate/init.py#L128),可作为迁移范本。
另外:如果你实现SettingsPluginmixin 的唯一目的就是访问数据目录,那么现在可以把这个 mixin 一并移除。
打印机交互(Printer interaction)
本节涉及的Printer类以self._printer形式注入到插件中。
Printer类的内部属性改名或移除
octoprint.printer.Printer的一些(私有)属性被重命名或移除。访问过下列属性的插件必须更新名称。注意:这些不是即插即用的替换!
受影响名称如下:
| 旧属性 | 新属性 |
|---|---|
_currentZ | _last_z |
_fileManager | _file_manager |
_printerProfileManager | _printer_profile_manager |
_selectedFile | _selected_job |
_comm | 仍可用,但会触发弃用警告,且仅当当前连接由内置 serial connector 插件提供时有效(替代访问方式见下节) |
以上新名称可在 src/octoprint/printer/standard.py 中找到佐证,例如self._last_z、self._selected_job: PrintJob、self._file_manager、self._printer_profile_manager等。
需要特别说明:官方明确提醒,插件不应使用 OctoPrint 内部类上的私有、未文档化属性。但如果你的插件确实依赖了这些实现细节,请到 OctoPrint 仓库提交 feature request,说明你缺少哪些官方插件接口与文档化内部 API,以便官方将其正式支持,避免未来再次踩坑。
Printer.get_transport已弃用
get_transport已被弃用(见 src/octoprint/printer/init.py#L937),其兼容层仅在当前打印机连接由内置 serial connector 插件提供时才可用。该兼容层计划在未来版本移除。
如果你的插件仍依赖self._printer.get_transport,官方建议现在就重构:自行检查 serial connector,然后获取_comm与其_serial对象——同时做好充分的错误检查(这些_前缀的私有属性不属于官方插件 API):
if self._printer.connection is None or self._connection.connector != "serial": return if hasattr(self._connection, "_comm"): # this gets you what used to be self._printer._comm... comm = self._connection._comm if hasattr(comm, "_serial"): # ... and this what used to be returned by self._printer.get_transport() serial = comm._serial同样,若有此类需求,请以 feature request 的形式联系官方,寻找不依赖实现细节的官方支持方案。
终端日志行格式改变
由串口连接产生的终端日志行不再带Recv:与Send:前缀,而是改用<<<与>>>。任何消费这些日志的解析器都必须更新。
内置默认终端过滤器已同步更新,其正则同时匹配新旧两种前缀,因此对第三方插件可能仍以旧格式输出的日志也能正常工作。旧版与新版的默认正则对照如下表:
| 名称 | 旧默认正则 | OctoPrint 2.0.0 默认正则 |
|---|---|---|
| Suppress temperature messages | (Send: (N\d+\s+)?M105)\|(Recv:\s+(ok\s+([PBN]\d+\s+)*)?([BCLPR]\|T\d*):-?\d+) | ((Send:\|>>>)\s+(N\d+\s+)?M105)\|((Recv:\|<<<)\s+(ok\s+([PBN]\d+\s+)*)?([BCLPR]\|T\d*):-?\d+) |
| Suppress SD status messages | (Send: (N\d+\s+)?M27)\|(Recv: SD printing byte)\|(Recv: Not SD printing) | ((Send:\|>>>)\s+(N\d+\s+)?M27)\|((Recv:\|<<<)\s+SD printing byte)\|((Recv:\|<<<)\s+Not SD printing) |
| Suppress position messages | (Send:\s+(N\d+\s+)?M114)\|(Recv:\s+(ok\s+)?X:[+-]?([0-9]*[.])?[0-9]+\s+Y:[+-]?([0-9]*[.])?[0-9]+\s+Z:[+-]?([0-9]*[.])?[0-9]+\s+E\d*:[+-]?([0-9]*[.])?[0-9]+).* | ((Send:\|>>>)\s+(N\d+\s+)?M114)\|((Recv:\|<<<)\s+(ok\s+)?X:[+-]?([0-9]*[.])?[0-9]+\s+Y:[+-]?([0-9]*[.])?[0-9]+\s+Z:[+-]?([0-9]*[.])?[0-9]+\s+E\d*:[+-]?([0-9]*[.])?[0-9]+).* |
| Suppress wait responses | Recv: wait | (Recv:\|<<<)\s+wait |
| Suppress processing responses | Recv: (echo:\s*)?busy:\s*processing | (Recv:\|<<<)\s+(echo:\s*)?busy:\s*processing |
新过滤器的默认配置同样体现在仓库的 src/octoprint/settings/init.py#L1863-L1867 与 src/octoprint/schema/config/terminalfilters.py 中,可作为核对基准。如果你的插件自定义了终端过滤器,请参照上表同步更新正则。
octoprint.printer.profile.BedTypes被移除
长期弃用的octoprint.printer.profile.BedTypes类型已移除,其即插即用替代品是命名更贴切的octoprint.printer.profile.BedFormFactor。
服务器(Server)
octoprint.server.util.flask.(admin|user)_validator被移除
octoprint.server.util.flask.admin_validator与octoprint.server.util.flask.user_validator均被移除,统一改用octoprint.server.util.flask.permissions_validator(相关代码位于 src/octoprint/server/util/flask.py)。
设置(Settings)
serial.*配置块已迁移
设置 schema 中的serial块迁移到了plugins.serial_connector,因为它现在由该内置插件管理。如果你的插件访问任何serial相关设置,需要调整访问路径。多数情况下只需把serial.*路径替换为plugins.serial_connector.*,但以下情况例外:
| 旧路径 | 新路径 |
|---|---|
serial.port | printerConnection.preferred.parameters.port |
serial.baudrate | printerConnection.preferred.parameters.baudrate |
serial.autoconnect | printerConnection.autoconnect |
serial.autorefresh | printerConnection.autorefresh |
serial.autorefreshInterval | printerConnection.autorefreshInterval |
serial.notifySuppressedCommands | feature.notifySuppressedCommands |
serial.alwaysSendChecksum、serial.neverSendChecksum | plugins.serial_connector.sendChecksum,取值always或never |
serial.disconnectOnErrors、serial.ignoreErrorsFromFirmware | plugins.serial_connector.errorHandling,取值disconnect或ignore |
serial.blacklistedPorts | plugins.serial_connector.blacklistedPorts(另见下方 blocklist 小节) |
serial.blacklistedBaudrates | plugins.serial_connector.blacklistedBaudrates(另见下方 blocklist 小节) |
仓库中 serial connector 插件的设置迁移逻辑可见于 src/octoprint/plugins/serial_connector/init.py#L102-L172,例如将disconnectOnErrors/ignoreErrorsFromFirmware映射为errorHandling(disconnect/ignore/cancel),将alwaysSendChecksum/neverSendChecksum映射为sendChecksum(always/never/print)。其 schema 定义在 src/octoprint/plugins/serial_connector/config_schema.py,其中errorHandling默认"disconnect"、sendChecksum默认"print"、blocklistedPorts: list[str]、blocklistedBaudrates: list[int]。
注意:目前存在兼容层代为执行这些映射,但请尽快迁移你的插件,以免在下一次弃用清理周期中被波及。
"blacklist"/"whitelist" 改为更具包容性的 "blocklist"/"allowlist"
以下包含 "blacklist" 或 "whitelist" 的路径名已迁移到更包容的 "blocklist"/"allowlist" 措辞,调用代码应相应调整:
| 旧路径 | 新路径 |
|---|---|
feature.autoUppercaseBlacklist | feature.autoUppercaseBlocklist |
server.pluginBlacklist | server.pluginBlocklist |
serial.blacklistedPorts | plugins.serial_connector.blocklistedPorts(另见上文 serial 小节) |
serial.blacklistedBaudrates | plugins.serial_connector.blocklistedBaudrates(另见上文 serial 小节) |
同样存在兼容层代为映射,但官方强烈建议尽快迁移。
octoprint.settings.Settings._config被移除
长期弃用的octoprint.settings.Settings._config字段已被移除。如需读取其旧值,请改用config属性。写入应极力避免,若万不得已,可通过_map.topmap完成。
工具函数(Util)
octoprint.util中以下长期弃用方法发生变化:
octoprint.util.bom_aware_open移除,改用带-sig后缀的编码自动处理 BOM,例如:with open(filename, encoding="utf-8-sig", mode="r") as f: # do somethingoctoprint.util.dict_clean移除,改用octoprint.util.dict_sanitize;octoprint.util.to_str移除,改用octoprint.util.to_bytes;octoprint.util.to_native_str移除,改用octoprint.util.to_unicode;octoprint.util.commandline.clean_ansi不再接受bytes输入,调用前请先转换为str;octoprint.util.json.dump移除,改用octoprint.util.json.dumps。
客户端变更
Viewmodels
usersViewModel被移除
usersViewModel早已弃用,它只是accessViewModel.users的转发。请直接改用后者作为即插即用替代。
FilesViewModel.requestData不再支持旧调用签名
以(focus, switchToPath, force)参数列表调用FilesViewModel.requestData不再受支持。请改用单个params参数:
const params = { focus: undefined, switchToPath: undefined, force: false } self.filesViewModel.requestData(params);FilesViewModel.fromResponse签名改变
FilesViewModel.fromResponse现在要求以(response, params)两个参数调用,与requestData的改动保持一致。
SettingsViewModel.requestData不再支持旧调用签名
以callback参数调用SettingsViewModel.requestData不再受支持,请改用返回的 Promise:
self.settingsViewModel.requestData() .done((response) => { // do something });onWizardTabChange被移除
该回调早已被onBeforeWizardTabChange取代,如果插件仍使用旧名称,请直接切换。
JS Client
已移除的 API 端点客户端
以下 JS Client 组件被移除,旁边是既有替代品:
| 已移除组件 | 替代组件 |
|---|---|
OctoPrintClient.logs | OctoPrintClient.plugins.logging |
OctoPrintClient.users | OctoPrintClient.access.users |
OctoPrintClient.getRequestHeaders不再支持旧调用签名
以额外 headers 作为第一个参数调用OctoPrintClient.getRequestHeaders不再受支持,调用方需要通过additional参数添加额外 headers。示例:
const headers = OctoPrintClient.getRequestHeaders( "POST", {"Some-Header": "Some Value"} )OctoPrintClient.deprecatedMethod被移除
若插件使用该方法,请改用OctoPrintClient.deprecated。
OctoPrintClient.deprecatedVariable签名改变
若插件使用该方法,请按新签名调整调用参数,具体细节参见OctoPrintClient.deprecatedVariable的文档。
API 变更
全局 API Key 不再自动生成
全局 API Key(Global API Key)已弃用一段时间,2.0.0 起启动时不再自动生成,因此可能为空,并将在 2.1.0 彻底移除。
插件代码需要调用 OctoPrint API 端点时,应改用self.plugin_apikey。示例:
import octoprint.plugin import requests class MyPlugin(octoprint.plugin.StartupPlugin): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._port = 5000 def on_startup(self, host, port, *args, **kwargs): self._port = port def fetch_api_version(self, **kwargs): url = f"https://localhost:{self._port}/api/version" headers = { "X-Api-Key": self.plugin_apikey } return requests.get(url, headers=headers, timeout=5)plugin_apikey由插件系统注入到每个插件实例,是官方推荐的、作用域限定于本插件的 API 访问凭证。
/api/logs/*、/api/users/*与/api/plugin/pluginmanager被移除
以下长期弃用的 API 端点已被移除,旁边是既有替代品:
| 已移除端点 | 替代端点 |
|---|---|
/api/logs/* | /plugin/logging/logs/* |
/api/users/* | /api/access/users/* |
/api/plugin/pluginmanager | /plugin/pluginmanager/(plugins|orphans|repository) |
仍依赖旧端点的客户端必须切换到新端点。
用户响应中的admin与user字段被移除
与用户相关的 API 响应不再包含admin和user字段。仍可从返回的groups中推断这两个信息。
Settings API 的权限检查更细粒度
Settings 检索端点 现在只返回用户按其权限实际需要的设置:
- 拥有
SETTINGS_READ权限时,只返回前端相关设置;用户无法写入的后端设置一概不返回; - 拥有
SETTINGS权限时,返回大部分后端相关设置,但访问控制相关设置与(已弃用的)全局 API Key 相关设置除外,这两类需要ADMIN权限; - 数据模型仍完整返回,但受限值会置为
null(单值)或空列表(列表)。
这印证了权限系统的细粒度设计:SETTINGS_READ、SETTINGS与ADMIN均定义在 src/octoprint/access/permissions.py 中。
项目组织变更
依赖变化
netifaces与passlib不再是 OctoPrint 的依赖。任何导入它们却没有将其声明为额外依赖的插件将无法再使用。如果你的插件依赖这两个第三方库的功能,必须在插件的setup.py或pyproject.toml中显式声明它们为依赖。
pyproject.toml与构建隔离
现在正是把插件从旧的setup.py构建方式迁移到 pyproject.toml 与构建隔离 的好时机。仓库中docs/plugins/examples/helloworld/下的示例插件(含pyproject.toml与Taskfile.yml)可作参考范本。
也为即将到来的移除做准备
在动手迁移的同时,请一并处理那些已有弃用警告的即将移除项。完整清单参见 当前弃用项列表。提前处理这些警告,可以避免未来再一次经历大规模迁移。
迁移检查清单(速查)
为便于对照执行,这里汇总官方文档的全部要点:
- 访问控制:
octoprint.access.users.*方法全部改为 snake_case;octoprint.users导入改octoprint.access.users;admin_permission/user_permission改GroupPermission(ADMIN_GROUP/USER_GROUP)或更细粒度权限。 - 文件存储:
FileDestinations.SDCARD值已变化,改用FileDestinations.PRINTER;UpdatedFiles只发printables类型。 - 插件系统:
BlueprintPlugin端点自动受 CSRF 保护,必要时用csrf_exempt()豁免;self._settings.get_plugin_data_folder改self.get_plugin_data_folder()。 - 打印机交互:私有属性按新名称更新;
get_transport改为自行探测 serial connector 的_comm._serial;终端日志前缀改为<<</>>>,同步更新过滤器正则;BedTypes改BedFormFactor。 - 服务器:
admin_validator/user_validator改permissions_validator。 - 设置:
serial.*迁移到plugins.serial_connector.*(含例外映射表);blacklist/whitelist 改 blocklist/allowlist;Settings._config改config属性。 - 工具:
bom_aware_open/dict_clean/to_str/to_native_str/json.dump按对应替代品迁移;clean_ansi只接受str。 - 客户端:
usersViewModel改accessViewModel.users;requestData统一使用params参数;fromResponse(response, params);settingsViewModel.requestData()用 Promise;onWizardTabChange改onBeforeWizardTabChange;JS Client 移除项按表替换。 - API:插件内改用
self.plugin_apikey;日志/用户/插件管理端点按表切换;用户响应去掉admin/user字段;Settings API 权限分级返回。 - 项目组织:显式声明
netifaces/passlib依赖;迁移到pyproject.toml与构建隔离。 - 前瞻:处理 deprecations.md 中已有的弃用警告项。
最后再次强调官方建议:即便上述条目与你无关,也请尽快落实pyproject.toml迁移与弃用警告清理,让插件在未来的版本迭代中持续可用。
- 物联网
- 后端
【免费下载链接】OctoPrint
OctoPrint is the snappy web interface for your 3D printer!
相关推荐
PyTorch Lightning 1.9 版本迁移完全指南:从废弃 API 到现代化训练实践
PyTorch Lightning 1.9 版本迁移完全指南:从废弃 API 到现代化训练实践 导读 本指南面向需要从 PyTorch Lightning 1.
人工智能深度学习机器学习预训练分布式训练微调终极IQKeyboardManager弃用API完全指南:从废弃方法到迁移策略
终极IQKeyboardManager弃用API完全指南:从废弃方法到迁移策略 IQKeyboardManager是iOS开发中解决键盘遮挡问题的高效库,能自动
移动开发UI组件Ceph mgr cli_api 模块实战指南:用 CLI 命令调用 ceph-mgr Python API 与性能基准测试
Ceph mgr cli_api 模块实战指南:用 CLI 命令调用 ceph mgr Python API 与性能基准测试 Ceph 的 cli_api 是
存储分布式文件系统对象存储后端高可用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考