bluesky-queueserver教程
本节教程的目的是探索队列服务器(Queue Server)的基本特性。教程中还简要介绍了队列服务器的功能、API,以及如何使用和何时使用这些功能的建议。
大多数教程需要两个终端:一个终端用于启动 Run Engine(RE)管理器,并显示日志消息和计划的控制台输出;另一个终端用于通过运行 CLI 命令与 RE 管理器交互。
RE 管理器是队列服务器的核心组件,它维护计划队列,创建 RE Worker 环境(执行计划的进程),并为客户端应用程序提供灵活的底层 0MQ API。以下教程提供了如何使用 qserver CLI 工具与 RE 管理器交互的说明,该工具可被视为一个基本的客户端应用程序。qserver 的功能仅限于发送单个 0MQ API 请求并显示收到的响应,但它提供了对几乎所有底层 API(批处理队列操作除外)的直接访问。使用 qserver -h 可以显示简要帮助和所有选项,或阅读 qserver 手册。
在生产系统中,用户更可能喜欢使用自定义 GUI 应用程序或在 IPython 中运行的 Bluesky 队列服务器 API 与 RE 管理器交互,但 qserver 仍然是一个便捷的工具,用于探索或演示队列服务器的功能,或者测试和调试已部署的系统。对使用 qserver 工具如何与 RE 管理器交互的说明也有助于理解底层 0MQ API 或更高级的 0MQ/HTTP Bluesky 队列服务器 API,这些 API 可用于开发 Python 应用程序。
启动队列服务器
在第一个终端, 以控制台程序启动RE管理器.
(apsbits_env) blctrl@blctrl-s3:~$ start-re-manager
[I 2026-04-22 11:36:47,452 bluesky_queueserver.manager.start_manager] RE Manager configuration:
...
RE Manager 的功能可以通过 CLI 参数进行定制。默认设置专为运行简单演示而选择,因此在大多数教程中,RE Manager 可以在不带参数的情况下启动。输入 start-re-manager -h 可显示所有支持的参数。更详细的描述请参阅应用程序手册。
RE Manager 的控制台输出包含服务器和 Bluesky 的日志消息,以及所执行计划(如 Live Tables)的文本输出。RE Manager 可配置为将控制台输出发布到 0MQ套接字,以便将其流式传输到其它应用程序(参见“RE Manager 控制台输出的远程监控”)。队列服务器的生产部署很可能将 RE Manager 作为服务运行,但将其作为控制台应用程序启动非常简单,推荐用于教程、演示以及软件开发和测试。
测试队列服务器是否正在运行且可访问的最简单方法是调用状态 API:
(apsbits_env) blctrl@blctrl-s3:~$ qserver status
Arguments: ['status']
11:48:27 - MESSAGE:
{'msg': 'RE Manager v0.0.23',
...,
'lock': {'environment': False, 'queue': False}}
服务器始终接受status API 请求,并返回反映 RE Manager 当前状态的参数集合。例如,'manager_state': 'idle' 表示 RE Manager 的当前状态,'worker_environment_exists': False 表示 RE Worker 环境是否已打开以及服务器是否准备好执行计划(当前环境不存在)。如果服务器无法访问或未及时响应,则会发生超时。RE Manager API 的详细参考可在“ZMQ 通信 API 支持的方法”一节中找到。RE Manager 应用程序可以随时通过按 Ctrl-C 停止。
注意: 当使用 Ctrl-C 组合键关闭 RE Manager 时,任何计划、任务、队列操作等的执行都会在没有警告或请求确认的情况下被中断。当 RE Manager 作为服务运行时,意外停止它没有风险。
打开或关闭RE Worker环境
使用在启动队列服务器中给出的介绍启动RE Mangager。
作为对打开 RE Worker 环境请求的响应,RE Manager 会创建一个新的 RE Worker 进程(用于执行 Bluesky 计划),配置 Run Engine 并将启动代码加载到 RE Worker 命名空间中。RE Manager 可以加载表示为启动文件集(IPython 风格)、Python 脚本或模块的启动代码。bluesky-queueserver 包包含一组带有模拟设备和计划的启动文件,足以用于简单的演示。除非指定了其他位置(参见“使用自定义启动代码运行 RE Manager”),否则 RE Manager 会加载内置的启动代码。
使用 qserver CLI 工具打开 RE Worker 环境:
(apsbits_env) blctrl@blctrl-s3:~$ qserver environment open
Arguments: ['environment', 'open']
14:19:15 - MESSAGE:
{'success': True, 'msg': ''}
返回的参数包括一个标志,用于指示请求是否被服务器接受('success': True),以及错误消息('msg': ''),如果请求被接受,则错误消息为空字符串。该 API 请求仅初始化打开环境的过程,此过程可能需要较长时间。返回结果 'success': True 并不意味着环境已成功加载或已完全加载。要判断环境是否已加载,请检查 RE Manager 的状态:
(apsbits_env) blctrl@blctrl-s3:~$ qserver status
Arguments: ['status']
14:24:47 - MESSAGE:
{'msg': 'RE Manager v0.0.23',
...
'manager_state': 'idle',
'queue_stop_pending': False,
'queue_autostart_enabled': False,
'worker_environment_exists': True,
'worker_environment_state': 'idle',
...}
打开环境失败的最可能原因是启动代码中引发了异常。请在 RE Manager 的控制台输出中搜索错误消息和回溯信息。
重复打开环境的请求将被服务器拒绝:
(apsbits_env) blctrl@blctrl-s3:~$ qserver environment open
Arguments: ['environment', 'open']
14:28:20 - MESSAGE:
{'success': False, 'msg': 'RE Worker environment already exists.'}
执行任何计划之前必须先打开环境。如果环境已关闭,启动计划队列的请求将被拒绝。所有队列操作(包括添加/删除/移动计划)都不需要环境打开。打开环境的过程可能会间接影响队列操作,因为它涉及根据加载的启动脚本生成现有/允许的计划和设备的新列表(参见“计划验证”)。
关闭 RE Worker 环境的操作涉及有序退出消息处理循环并关闭工作进程。关闭环境是安全的,因为只有在没有计划或前台任务运行时才能执行此操作。如果环境繁忙,请求将被拒绝。
使用 qserver CLI 工具关闭 RE Worker 环境:
(apsbits_env) blctrl@blctrl-s3:~$ qserver environment close
Arguments: ['environment', 'close']
14:35:41 - MESSAGE:
{'success': True, 'msg': ''}
该 API 请求仅启动关闭环境的过程。请检查 RE Manager 的状态以确定环境是否已成功关闭:
(apsbits_env) blctrl@blctrl-s3:~$ qserver status
Arguments: ['status']
14:39:17 - MESSAGE:
{
...
'manager_state': 'idle',
'queue_stop_pending': False,
'queue_autostart_enabled': False,
'worker_environment_exists': False,
'worker_environment_state': 'closed',
...
}
关闭环境的重复请求被拒绝:
apsbits_env) blctrl@blctrl-s3:~$ qserver environment close
Arguments: ['environment', 'close']
14:41:15 - MESSAGE:
{'success': False, 'msg': 'RE Worker environment does not exist.'}
RE Worker 环境旨在以 Bluesky 计划或用户定义函数的形式运行用户代码。如果主线程陷入无限循环或无限等待(例如,等待无超时的无响应 PV),环境可能会变得无响应且无法关闭。这可能会给光束线的远程操作带来极大不便。RE Manager 支持一种 API,可通过销毁无响应的环境(终止 RE Worker 进程)来从这种状态中恢复。环境被销毁后,可以打开新环境并恢复操作。销毁环境的操作是不安全的,如果在正常操作期间意外发送请求,将终止任何正在运行的计划或任务。
使用以下命令启动销毁 RE Worker 环境的过程:
(apsbits_env) blctrl@blctrl-s3:~$ qserver environment destroy
Arguments: ['environment', 'destroy']
14:49:44 - MESSAGE:
{'success': True, 'msg': ''}
操作结束可能花费一点时间。检查状态确认环境处于关闭状态并且RE Mangage是空闲的。
向队列添加项目
队列操作(例如添加和移除项目、替换或移动现有项目)可以随时执行。操作队列无需打开环境。队列服务器会对提交的计划进行验证,并拒绝那些不存在或用户无权执行的计划。计划可以接受设备作为参数值。这些设备必须在提交计划的用户的允许设备列表中,否则计划将被拒绝(如果计划参数经过验证)或在计划执行期间失败。
按照“启动队列服务器”中的说明启动 RE Manager。
显示允许的计划和设备列表。请注意,scan 和 count 计划位于允许计划列表中:
(apsbits_env) blctrl@blctrl-s3:~$ qserver allowed plans
Arguments: ['allowed', 'plans']
15:01:44 - MESSAGE:
{'success': True,
'msg': '',
'plans_allowed': {'adaptive_scan': '{...}',
'count': '{...}',
'count_bundle_test': '{...}',
'fly': '{...}',
'grid_scan': '{...}',
'inner_product_scan': '{...}',
'list_grid_scan': '{...}',
'list_scan': '{...}',
'log_scan': '{...}',
'marked_up_count': '{...}',
'move_then_count': '{...}',
'mv': '{...}',
'mvr': '{...}',
'null': '{...}',
'plan_test_progress_bars': '{...}',
'ramp_plan': '{...}',
'rel_adaptive_scan': '{...}',
'rel_grid_scan': '{...}',
'rel_list_grid_scan': '{...}',
'rel_list_scan': '{...}',
'rel_log_scan': '{...}',
'rel_scan': '{...}',
'rel_spiral': '{...}',
'rel_spiral_fermat': '{...}',
'rel_spiral_square': '{...}',
'relative_inner_product_scan': '{...}',
'scan': '{...}',
'scan_nd': '{...}',
'sim_multirun_plan_nested': '{...}',
'spiral': '{...}',
'spiral_fermat': '{...}',
'spiral_square': '{...}',
'tune_centroid': '{...}',
'tweak': '{...}',
'x2x_scan': '{...}'},
'plans_allowed_uid': 'dea8e341-f563-4108-ac38-e6dfb227d7f1'}
det1、det2 和 motor 位于允许设备列表中。qserver 工具仅显示顶层的设备名称集,但子设备名称也可以用作计划参数:
(apsbits_env) blctrl@blctrl-s3:~$ qserver allowed devices
Arguments: ['allowed', 'devices']
15:03:03 - MESSAGE:
{'success': True,
'msg': '',
'devices_allowed': {'ab_det': '{...}',
'bool_sig': '{...}',
'custom_test_device': '{...}',
'custom_test_flyer': '{...}',
'custom_test_signal': '{...}',
'det': '{...}',
'det1': '{...}',
'det2': '{...}',
'det3': '{...}',
'det4': '{...}',
'det5': '{...}',
'det_with_conf': '{...}',
'det_with_count_time': '{...}',
'direct_img': '{...}',
'direct_img_list': '{...}',
'flyer1': '{...}',
'flyer2': '{...}',
'identical_det': '{...}',
'img': '{...}',
'invariant1': '{...}',
'invariant2': '{...}',
'jittery_motor1': '{...}',
'jittery_motor2': '{...}',
'motor': '{...}',
'motor1': '{...}',
'motor2': '{...}',
'motor3': '{...}',
'motor_empty_hints1': '{...}',
'motor_empty_hints2': '{...}',
'motor_no_hints1': '{...}',
'motor_no_hints2': '{...}',
'motor_no_pos': '{...}',
'new_trivial_flyer': '{...}',
'noisy_det': '{...}',
'pseudo1x3': '{...}',
'pseudo3x3': '{...}',
'rand': '{...}',
'rand2': '{...}',
'sig': '{...}',
'signal': '{...}',
'sim_bundle_A': '{...}',
'sim_bundle_B': '{...}',
'trivial_flyer': '{...}'},
'devices_allowed_uid': '78174aa0-7ea0-4975-b1d0-6b361d8db72b'}
首先, 我们清除这个队列, 由于它可能已经包含计划:
(apsbits_env) blctrl@blctrl-s3:~$ qserver queue clear
Arguments: ['queue', 'clear']
15:05:40 - MESSAGE:
{'success': True, 'msg': ''}
验证在队列中项目数为0:
(apsbits_env) blctrl@blctrl-s3:~$ qserver status
Arguments: ['status']
15:06:27 - MESSAGE:
{'msg': 'RE Manager v0.0.23',
'items_in_queue': 0,
...
}
加载队列的内容, 此时它应该是空的:
(apsbits_env) blctrl@blctrl-s3:~$ qserver queue get
Arguments: ['queue', 'get']
15:08:05 - MESSAGE:
{'success': True,
'msg': '',
'items': [],
'running_item': {},
'plan_queue_uid': '65ee0cbf-eded-40eb-8997-cf7374e17dcf'}
现在, 我们添加计划count([det1, det2], num=5, delay=1)到这个队列:
(apsbits_env) blctrl@blctrl-s3:~$ qserver queue add plan '{"name": "count", "args": [["det1", "det2"]] , "kwargs": {"num": 5, "delay": 1}}'
Arguments: ['queue', 'add', 'plan', '{"name": "count", "args": [["det1", "det2"]], "kwargs": {"num": 5, "delay": 1}}']
15:42:43 - MESSAGE:
{'success': True,
'msg': '',
'qsize': 1,
'item': {'name': 'count',
'args': [['det1', 'det2']],
'kwargs': {'num': 5, 'delay': 1},
'item_type': 'plan',
'user': 'qserver-cli',
'user_group': 'primary',
'item_uid': '36aafa7e-709c-4aa8-8859-fff2e8a39a70'}}
提交的计划被服务器接受, 并且被添加到了队列中。参数'qsize':1表示这个计划队列的新大小。验证这个队列大小并且加载更新的队列:
(apsbits_env) blctrl@blctrl-s3:~$ qserver status
Arguments: ['status']
15:45:38 - MESSAGE:
{'msg': 'RE Manager v0.0.23',
'items_in_queue': 1,
...}
(apsbits_env) blctrl@blctrl-s3:~$ qserver queue get
Arguments: ['queue', 'get']
15:46:39 - MESSAGE:
{'success': True,
'msg': '',
'items': [{'name': 'count',
'args': [['det1', 'det2']],
'kwargs': {'num': 5, 'delay': 1},
'item_type': 'plan',
'user': 'qserver-cli',
'user_group': 'primary',
'item_uid': '36aafa7e-709c-4aa8-8859-fff2e8a39a70'}],
'running_item': {},
'plan_queue_uid': '81df5852-3a4c-44e5-b682-cdde8c5f53bc'}
默认项目被添加到队列末尾。添加另一个计划scan([det1,det2], motor, -1, 1, 10)到这个队列:
(apsbits_env) blctrl@blctrl-s3:~$ qserver queue add plan '{"name": "scan", "args": [["det1", "det2"], "motor", -1, 1, 10]}'
Arguments: ['queue', 'add', 'plan', '{"name": "scan", "args": [["det1", "det2"], "motor", -1, 1, 10]}']
15:48:56 - MESSAGE:
{'success': True,
'msg': '',
'qsize': 2,
'item': {'name': 'scan',
'args': [['det1', 'det2'], 'motor', -1, 1, 10],
'item_type': 'plan',
'user': 'qserver-cli',
'user_group': 'primary',
'item_uid': 'b02a004d-3451-46b6-9292-be0b31ee1bb2'}}
注意: 队列大小现在是2。加载队列项目的列表并且验证scan计划是被添加到队列末尾:
(apsbits_env) blctrl@blctrl-s3:~$ qserver queue get
Arguments: ['queue', 'get']
15:50:41 - MESSAGE:
{'success': True,
'msg': '',
'items': [{'name': 'count',
'args': [['det1', 'det2']],
'kwargs': {'num': 5, 'delay': 1},
'item_type': 'plan',
'user': 'qserver-cli',
'user_group': 'primary',
'item_uid': '36aafa7e-709c-4aa8-8859-fff2e8a39a70'},
{'name': 'scan',
'args': [['det1', 'det2'], 'motor', -1, 1, 10],
'item_type': 'plan',
'user': 'qserver-cli',
'user_group': 'primary',
'item_uid': 'b02a004d-3451-46b6-9292-be0b31ee1bb2'}],
'running_item': {},
'plan_queue_uid': '6f56920c-96e7-40d0-a9f6-94a26890fa1c'}
RE Manager API 支持大量扩展选项来定义插入计划的位置。例如,可以将计划插入到队列的前端:
(apsbits_env) blctrl@blctrl-s3:~$ qserver queue add plan front '{"name": "scan", "args": [["det1"], "motor", -2, 2, 5]}'
Arguments: ['queue', 'add', 'plan', 'front', '{"name": "scan", "args": [["det1"], "motor", -2, 2, 5]}']
15:53:20 - MESSAGE:
{'success': True,
'msg': '',
'qsize': 3,
'item': {'name': 'scan',
'args': [['det1'], 'motor', -2, 2, 5],
'item_type': 'plan',
'user': 'qserver-cli',
'user_group': 'primary',
'item_uid': '67e100b5-517f-413d-aba9-56401ddd0699'}}
验证这个新计划被插入到了队列首部:
(apsbits_env) blctrl@blctrl-s3:~$ qserver queue get
Arguments: ['queue', 'get']
15:53:34 - MESSAGE:
{'success': True,
'msg': '',
'items': [{'name': 'scan',
'args': [['det1'], 'motor', -2, 2, 5],
'item_type': 'plan',
'user': 'qserver-cli',
'user_group': 'primary',
'item_uid': '67e100b5-517f-413d-aba9-56401ddd0699'},
{'name': 'count',
'args': [['det1', 'det2']],
'kwargs': {'num': 5, 'delay': 1},
'item_type': 'plan',
'user': 'qserver-cli',
'user_group': 'primary',
'item_uid': '36aafa7e-709c-4aa8-8859-fff2e8a39a70'},
{'name': 'scan',
'args': [['det1', 'det2'], 'motor', -1, 1, 10],
'item_type': 'plan',
'user': 'qserver-cli',
'user_group': 'primary',
'item_uid': 'b02a004d-3451-46b6-9292-be0b31ee1bb2'}],
'running_item': {},
'plan_queue_uid': '1352f834-1d3a-4693-be31-2d07ecd7204e'}
队列中可以包含由 RE Manager 执行并控制队列执行的指令。目前唯一支持的指令是 queue_stop,它用于停止队列的执行(例如,让操作员更换样品)。之后可以重新启动队列。以下命令将在队列中位置为 -2 的元素之前插入该指令:
(apsbits_env) blctrl@blctrl-s3:~$ qserver queue add instruction -2 queue-stop
Arguments: ['queue', 'add', 'instruction', '-2', 'queue-stop']
15:58:29 - MESSAGE:
{'success': True,
'msg': '',
'qsize': 4,
'item': {'name': 'queue_stop',
'item_type': 'instruction',
'user': 'qserver-cli',
'user_group': 'primary',
'item_uid': 'f1a7c250-f3c9-45c3-84d6-3879efa415b0'}}
(apsbits_env) blctrl@blctrl-s3:~$ qserver queue get
Arguments: ['queue', 'get']
15:58:43 - MESSAGE:
{'success': True,
'msg': '',
'items': [{'name': 'scan',
'args': [['det1'], 'motor', -2, 2, 5],
'item_type': 'plan',
'user': 'qserver-cli',
'user_group': 'primary',
'item_uid': '67e100b5-517f-413d-aba9-56401ddd0699'},
{'name': 'count',
'args': [['det1', 'det2']],
'kwargs': {'num': 5, 'delay': 1},
'item_type': 'plan',
'user': 'qserver-cli',
'user_group': 'primary',
'item_uid': '36aafa7e-709c-4aa8-8859-fff2e8a39a70'},
{'name': 'queue_stop',
'item_type': 'instruction',
'user': 'qserver-cli',
'user_group': 'primary',
'item_uid': 'f1a7c250-f3c9-45c3-84d6-3879efa415b0'},
{'name': 'scan',
'args': [['det1', 'det2'], 'motor', -1, 1, 10],
'item_type': 'plan',
'user': 'qserver-cli',
'user_group': 'primary',
'item_uid': 'b02a004d-3451-46b6-9292-be0b31ee1bb2'}],
'running_item': {},
'plan_queue_uid': '42ebe64a-2e21-4332-bc09-7c56f9b30ab4'}
请注意,使用负索引来定位队列项(从队列末尾开始计数)更为可靠,因为队列操作可能在队列运行期间执行,且项可能随时从队列前端被移除。或者,也可以使用 item_uid 来定位项,该标识符不会因队列操作而改变。
启动和停止队列
使用启动队列服务器中给出的指令启动RE管理器。
按照“向队列添加项”中所述的方法清空队列并向其中添加几个计划。在本教程中,建议使用执行时间相对较长的计划。例如,以下计划运行约 20 秒:
(apsbits_env) blctrl@blctrl-s3:~$ qserver queue add plan '{"name": "count", "args": [["det1", "det2"]], "kwargs": {"num": 10, "delay": 2}}'
(apsbits_env) blctrl@blctrl-s3:~$ qserver queue add plan '{"name": "count", "args": [["det1", "det2"]], "kwargs": {"num": 10, "delay": 2}}'
(apsbits_env) blctrl@blctrl-s3:~$ qserver queue add plan '{"name": "count", "args": [["det1", "det2"]], "kwargs": {"num": 10, "delay": 2}}'
在以下示例中, 我们认为这个队列包含3个count计划, 这个队列执行时间约为60秒:
(apsbits_env) blctrl@blctrl-s3:~$ qserver queue get
Arguments: ['queue', 'get']
13:34:42 - MESSAGE:
{'success': True,
'msg': '',
'items': [{'name': 'count',
'args': [['det1', 'det2']],
'kwargs': {'num': 10, 'delay': 2},
'item_type': 'plan',
'user': 'qserver-cli',
'user_group': 'primary',
'item_uid': '74d4815a-e77d-486d-bd73-5a04622e8896'},
{'name': 'count',
'args': [['det1', 'det2']],
'kwargs': {'num': 10, 'delay': 2},
'item_type': 'plan',
'user': 'qserver-cli',
'user_group': 'primary',
'item_uid': 'fac73cc5-b517-4304-9106-25af1a8b3802'},
{'name': 'count',
'args': [['det1', 'det2']],
'kwargs': {'num': 10, 'delay': 2},
'item_type': 'plan',
'user': 'qserver-cli',
'user_group': 'primary',
'item_uid': '9956a4b4-dfcc-4905-b696-c7b38d39e9cc'}],
'running_item': {},
'plan_queue_uid': '58c17f21-5362-441b-a39d-49e047f48959'}
在打开和关闭RE Worker环境中描述的, 打开这个环境。
由RE管理器执行的每个计划被添加到了计划历史。设计这个历史不是为了长期存储, 并且必须被周期地清理:
(apsbits_env) blctrl@blctrl-s3:~$ qserver history clear
Arguments: ['history', 'clear']
13:37:31 - MESSAGE:
{'success': True, 'msg': ''}
在历史中项目数以RE管理器状态被报告:
(apsbits_env) blctrl@blctrl-s3:~$ qserver status
Arguments: ['status']
13:38:31 - MESSAGE:
{...
'items_in_queue': 3,
'items_in_history': 0
}
启动队列,并观察运行 RE Manager 的终端中显示的日志消息和 Live Table('success': True 表示请求已被服务器接受,队列即将开始执行):
(apsbits_env) blctrl@blctrl-s3:~$ qserver environment open
Arguments: ['environment', 'open']
13:42:08 - MESSAGE:
{'success': True, 'msg': ''}
(apsbits_env) blctrl@blctrl-s3:~$ qserver queue start
Arguments: ['queue', 'start']
13:42:12 - MESSAGE:
{'success': True, 'msg': ''}
当第一个计划仍然运行时, 检查队列的内容: running_item是当前运行计划的参数的字典, 而items是还在队列中的计划列表:
(apsbits_env) blctrl@blctrl-s3:~$ qserver queue get
Arguments: ['queue', 'get']
13:45:55 - MESSAGE:
{'success': True,
'msg': '',
'items': [{'name': 'count',
'args': [['det1', 'det2']],
'kwargs': {'num': 10, 'delay': 2},
'item_type': 'plan',
'user': 'qserver-cli',
'user_group': 'primary',
'item_uid': 'd03f8450-82ef-443c-944b-f92a8493952b'},
{'name': 'count',
'args': [['det1', 'det2']],
'kwargs': {'num': 10, 'delay': 2},
'item_type': 'plan',
'user': 'qserver-cli',
'user_group': 'primary',
'item_uid': '376c3b4e-e06d-4d4e-83f4-2b19d9aa2fc5'}],
'running_item': {'name': 'count',
'args': [['det1', 'det2']],
'kwargs': {'num': 10, 'delay': 2},
'item_type': 'plan',
'user': 'qserver-cli',
'user_group': 'primary',
'item_uid': '6397accd-623a-4689-8bf4-13d2715637b2',
'properties': {'time_start': 1776923150.0495641}},
'plan_queue_uid': 'c33863b9-b804-4bbc-a701-4f90abd064b0'}
一旦所有计划结束, 验证RE管理器状态来确保队列是空的并且正确数目的计划被添加到历史:
(apsbits_env) blctrl@blctrl-s3:~$ qserver status
Arguments: ['status']
13:47:43 - MESSAGE:
{...
'items_in_queue': 0,
'items_in_history': 6
...}
所有用于操作队列的功能在队列运行时都是可用的。向队列中添加几个计划,启动队列,然后尝试在队列运行时向其中添加计划。检查队列内容(使用 qserver queue get)以观察变化。
RE Manager 支持一种 API,允许在当前计划完成后停止队列执行。此 API 旨在用于当前正在运行的计划应正常完成,但在下一个计划开始前需要操作员进行某些干预(例如调整样品)的情况。该 API 调用不会影响当前正在运行的计划。
向队列中添加更多计划并启动队列。当第一个计划正在运行时,使用以下命令停止队列:
(apsbits_env) blctrl@blctrl-s3:~$ qserver queue stop
Arguments: ['queue', 'stop']
13:54:33 - MESSAGE:
{'success': True, 'msg': ''}
当计划仍在运行时, 检查RE管理器状态的当前状态(queue_stop_pending):
(apsbits_env) blctrl@blctrl-s3:~$ qserver status
Arguments: ['status']
13:54:39 - MESSAGE:
{...
'manager_state': 'executing_queue',
'queue_stop_pending': True,
...}
观察到队列在当前计划完成后停止。请注意,命令序列(qserver queue start、qserver queue stop 和 qserver status)必须在计划运行时发出。如果需要,可以增大 num 或 delay 计划参数的值,使计划运行时间更长。
由于计划可能需要很长时间(可能数小时)才能执行完毕,操作员可能会错误地发送停止队列的 API 请求,或者在计划运行期间改变主意,因此 RE Manager 允许取消挂起的停止队列请求。在计划仍在运行时,快速连续执行以下命令,观察 queue_stop_pending 状态参数的变化:
(apsbits_env) blctrl@blctrl-s3:~$ qserver queue start
Arguments: ['queue', 'start']
14:04:22 - MESSAGE:
{'success': True, 'msg': ''}
(apsbits_env) blctrl@blctrl-s3:~$ qserver queue stop
Arguments: ['queue', 'stop']
14:04:26 - MESSAGE:
{'success': True, 'msg': ''}
(apsbits_env) blctrl@blctrl-s3:~$ qserver status
Arguments: ['status']
14:04:33 - MESSAGE:
{'msg': 'RE Manager v0.0.23',
'items_in_queue': 2,
...
'manager_state': 'executing_queue',
'queue_stop_pending': True,
}
(apsbits_env) blctrl@blctrl-s3:~$ qserver queue stop cancel
Arguments: ['queue', 'stop', 'cancel']
14:04:39 - MESSAGE:
{'success': True, 'msg': ''}
(apsbits_env) blctrl@blctrl-s3:~$ qserver status
Arguments: ['status']
14:04:43 - MESSAGE:
{...
'queue_stop_pending': False,
...}
计划执行将持续到队列为空。
与运行引擎交互
RE Manager 隐藏了与计划执行相关的大部分底层细节,但某些与 Run Engine 监控和控制相关的功能可通过 0MQ API 访问:
- 状态参数:re_state 指示 Run Engine 的当前状态,pause_pending 指示 Run Engine 是否有挂起的延迟暂停。
- 用于暂停、恢复、停止、中止或终止正在运行计划的 0MQ API。有关 Run Engine 如何处理计划中断的更详细信息,请参阅 Bluesky 文档。
如果 RE Worker 环境已关闭,则 Run Engine 不会被实例化,re_state 始终为 None,pause_pending 为 False:
$ qserver status
14:59:09 - MESSAGE:
{ ...
'pause_pending': False,
...
're_state': None,
... }
如果环境打开, 接着re_state是一个表示运行引擎实际状态的字符串:
$ qserver status
16:19:30 - MESSAGE:
{ ...
'pause_pending': False,
...
're_state': 'idle',
... }
中断当前正在运行计划的执行的操作由 Run Engine 处理。RE Manager 提供了用于发起计划中断的 API,包括暂停计划,然后恢复、停止、中止或终止已暂停的计划。请注意,停止队列的 API 与停止已暂停计划的 API 并不相关,唯一的关联是:如果计划被停止、中止、终止或因任何其他方式未能完成,队列会自动停止。
假设 RE Worker 环境已打开。向队列中添加一个计划。以下计划运行一分钟,应能很好地用于演示:
(apsbits_env) blctrl@blctrl-s3:~$ qserver queue add plan '{"name": "count", "args": [["det1", "det2"]], "kwargs": {"num": 6, "delay": 10}}'
count 计划在每次测量前都包含一个检查点(checkpoint)。该 API 允许发起延迟暂停和立即暂停。在延迟暂停的情况下(相当于在 IPython 中按一次 Ctrl-C),计划将执行到下一个检查点,即完成当前测量,并在计划恢复后开始下一次测量。在立即暂停的情况下(相当于在 IPython 中按两次 Ctrl-C),计划将回滚到上一个检查点,并在计划恢复后重复当前测量。该计划执行 6 次测量,每次测量间隔 10 秒,因此很容易观察暂停和恢复计划的操作是如何工作的:
# 启动队列
$ qserver queue start
# 请求延时暂停
$ qserver re pause
16:59:59 - MESSAGE:
{'msg': '', 'success': True}
# 在计划仍在运行时检查状态, 但延迟暂停是即将发生
$ qserver status
Arguments: ['status']
{ ...
'manager_state': 'executing_queue',
...
'pause_pending': True,
...
're_state': 'running',
...}
# 计划被暂停,立即检查状态(需要几秒钟达到下个检查点)
$ qserver status
17:00:25 - MESSAGE:
{ ...
'manager_state': 'paused',
...
'pause_pending': False,
...
're_state': 'paused',
...}
# 继续计划
$ qserver re resume
17:07:08 - MESSAGE:
{'msg': '', 'success': True}
RE Manager 的输出包含以下实时表格。请注意,第一次测量已完全完成,并且在计划恢复后没有重复执行:
Transient Scan ID: 13 Time: 2026-04-23 14:54:13
Persistent Unique Scan ID: '523b58a4-fb8f-4d21-b355-297aeedb2288'
New stream: 'primary'
+-----------+------------+------------+------------+
| seq_num | time | det1 | det2 |
+-----------+------------+------------+------------+
| 1 | 14:54:13.5 | 5.000 | 1.765 |
| 2 | 14:54:23.6 | 5.000 | 1.765 |
[I 2026-04-23 14:54:28,689 bluesky_queueserver.manager.manager] Pausing the queue (currently running plan) ...
[I 2026-04-23 14:54:28,689 bluesky_queueserver.manager.worker] Pausing Run Engine ...
Deferred pause acknowledged. Continuing to checkpoint.
Pausing...
[I 2026-04-23 14:54:34,123 bluesky_queueserver.manager.worker] The plan is paused ...
[I 2026-04-23 14:55:59,291 bluesky_queueserver.manager.manager] Resuming paused plan ...
[I 2026-04-23 14:55:59,292 bluesky_queueserver.manager.worker] Run Engine: resume
[I 2026-04-23 14:55:59,292 bluesky_queueserver.manager.worker] Continue plan execution with the option 'resume'
| 3 | 14:55:59.2 | 5.000 | 1.765 |
| 4 | 14:55:59.3 | 5.000 | 1.765 |
| 5 | 14:56:09.3 | 5.000 | 1.765 |
| 6 | 14:56:19.3 | 5.000 | 1.765 |
[I 2026-04-23 14:56:29,331 bluesky_queueserver.manager.plan_monitoring] Run was closed: '523b58a4-fb8f-4d21-b355-297aeedb2288'
+-----------+------------+------------+------------+
generator count ['523b58a4'] (scan num: 13)
以下命令序列用于启动队列并请求立即暂停。该序列可使用同一计划进行测试:
(apsbits_env) blctrl@blctrl-s3:~$ qserver queue add plan '{"name": "count", "args":
(apsbits_env) blctrl@blctrl-s3:~$ qserver queue start
(apsbits_env) blctrl@blctrl-s3:~$ qserver re pause immediate
(apsbits_env) blctrl@blctrl-s3:~$ qserver re resume
在实时表格中, 当计划被暂停时, 测量#2被取消, 并且在计划继续时, 重复:
Transient Scan ID: 16 Time: 2026-04-23 15:03:51
Persistent Unique Scan ID: 'c408db33-ed51-41b9-b984-59ad26d8dea0'
New stream: 'primary'
+-----------+------------+------------+------------+
| seq_num | time | det1 | det2 |
+-----------+------------+------------+------------+
| 1 | 15:03:51.5 | 5.000 | 1.765 |
| 2 | 15:04:01.5 | 5.000 | 1.765 |
[I 2026-04-23 15:04:06,274 bluesky_queueserver.manager.manager] Pausing the queue (currently running plan) ...
[I 2026-04-23 15:04:06,275 bluesky_queueserver.manager.worker] Pausing Run Engine ...
Pausing...
[I 2026-04-23 15:04:06,276 bluesky_queueserver.manager.worker] The plan is paused ...
[I 2026-04-23 15:04:16,248 bluesky_queueserver.manager.manager] Resuming paused plan ...
[I 2026-04-23 15:04:16,249 bluesky_queueserver.manager.worker] Run Engine: resume
[I 2026-04-23 15:04:16,249 bluesky_queueserver.manager.worker] Continue plan execution with the option 'resume'
| 2 | 15:04:16.2 | 5.000 | 1.765 |
计划暂停后,可以恢复(如已演示的那样)、停止、中止或终止。除了“停止”的计划被视为成功完成,而“中止”和“终止”的计划被视为失败之外,这三种终止计划的方法在技术上的差异相对较小;计划停止或取消后可以立即启动新计划,但计划终止后需要重新启动环境(关闭并再次打开)。
各自的qserver命令:
$ qserver re stop #停止
$ qserver re abort #取消
$ qserver re halt #中止
计划的立即执行
RE Manager 允许提交单个计划以立即执行,而无需将其放入队列或更改队列内容(参见“计划的立即执行”)。本教程演示了如何提交单个计划并获取其执行结果。
按照“启动队列服务器”中的说明启动 RE Manager。
打开环境:
(apsbits_env) blctrl@blctrl-s3:~$ qserver environment open
Arguments: ['environment', 'open']
15:12:20 - MESSAGE:
{'success': True, 'msg': ''}
检查RE管理器的状态:
(apsbits_env) blctrl@blctrl-s3:~$ qserver status
Arguments: ['status']
15:13:06 - MESSAGE:
{'msg': 'RE Manager v0.0.23',
'items_in_queue': 0,
...
'manager_state': 'idle',
...
're_state': 'idle',
...}
RE Manager 和 Run Engine 的状态为空闲,这意味着该计划将被接受。
现在,启动之前教程中使用的同一个计数计划。计划将立即开始执行:
(apsbits_env) blctrl@blctrl-s3:~$ qserver queue execute plan '{"name": "count", "args": [["det1", "det2"]], "kwargs": {"num": 10, "delay": 1}}'
检查计划历史中的最后一项,以确保计划已成功完成。将接受执行时的计划的 item_uid 与历史记录中计划的 item_uid 进行比较:
(apsbits_env) blctrl@blctrl-s3:~$ qserver history get
执行函数
RE Manager 允许在 RE Worker 进程中启动函数执行(参见“执行函数”)。RE Manager 默认加载的演示启动代码定义了一个函数 function_sleep,该函数接受一个参数(函数的执行时间),并返回一个包含成功标志(始终为 True)和作为参数传递的时间值的字典。演示的默认权限已配置为允许primary用户调用此函数。该函数方便演示和测试,因为它允许设置函数的执行时间,并通过查看控制台输出来观察函数开始和结束的时间:
def function_sleep(time):
"""
Sleep for a given number of seconds.
"""
print("******** Starting execution of the function 'function_sleep' **************")
print(f"******************* Waiting for {time} seconds **************************")
ttime.sleep(time)
print("******** Finished execution of the function 'function_sleep' **************")
return {"success": True, "time": time}
启动 RE Manager,打开环境,并验证 RE Manager 处于空闲状态。使用与“计划的立即执行”中相同的步骤。开始执行函数。较长的延迟(60 秒)可以为实验留出充足的时间:
(apsbits_env) blctrl@blctrl-s3:~$ qserver function execute '{"name": "function_sleep", "args": [60], "kwargs": {}}'
Arguments: ['function', 'execute', '{"name": "function_sleep", "args": [60], "kwargs": {}}']
15:28:29 - MESSAGE:
{'success': True,
'msg': '',
'item': {'name': 'function_sleep',
'args': [60],
'kwargs': {},
'user': 'qserver-cli',
'user_group': 'primary',
'item_uid': '6cf5679d-2205-431d-915d-b976cf2e9cea'},
'task_uid': '6cf5679d-2205-431d-915d-b976cf2e9cea'}
该函数当前作为前台任务运行。检查 RE Manager 的状态。请注意,manager_state 和 worker_environment_state 被设置为 'executing_task',且在 worker 环境中运行的后台任务数量为 0:
(apsbits_env) blctrl@blctrl-s3:~$ qserver status
Arguments: ['status']
15:33:16 - MESSAGE:
{'msg': 'RE Manager v0.0.23',
...
'manager_state': 'executing_task',
'queue_stop_pending': False,
'queue_autostart_enabled': False,
'worker_environment_exists': True,
'worker_environment_state': 'executing_task',
'worker_background_tasks': 0,
're_state': 'idle',
检查任务状态, 她现在以'running'返回:
(apsbits_env) blctrl@blctrl-s3:~$ qserver task status 'f22342b3-ba18-47a9-8936-abc53d11cec5'
Arguments: ['task', 'status', 'f22342b3-ba18-47a9-8936-abc53d11cec5']
15:36:29 - MESSAGE:
{'success': True,
'msg': '',
'task_uid': 'f22342b3-ba18-47a9-8936-abc53d11cec5',
'status': 'running'}
查看RE管理器的调试输出并且等到函数退出. 再次检查任务状态, 它现在变为了'completed':
(apsbits_env) blctrl@blctrl-s3:~$ qserver task status 'f22342b3-ba18-47a9-8936-abc53d11cec5'
Arguments: ['task', 'status', 'f22342b3-ba18-47a9-8936-abc53d11cec5']
15:38:21 - MESSAGE:
{'success': True,
'msg': '',
'task_uid': 'f22342b3-ba18-47a9-8936-abc53d11cec5',
'status': 'completed'}
现在加载任务执行的结果. return_value字段表示函数的返回值, 并且被序列化为JSON:
(apsbits_env) blctrl@blctrl-s3:~$ qserver task result 'f22342b3-ba18-47a9-8936-abc53d11cec5'
Arguments: ['task', 'result', 'f22342b3-ba18-47a9-8936-abc53d11cec5']
15:39:34 - MESSAGE:
{'success': True,
'msg': '',
'task_uid': 'f22342b3-ba18-47a9-8936-abc53d11cec5',
'status': 'completed',
'result': {'task_uid': 'f22342b3-ba18-47a9-8936-abc53d11cec5',
'success': True,
'msg': '',
'traceback': '',
'return_value': {'success': True, 'time': 60},
'time_start': 1776929763.0825527,
'time_stop': 1776929823.0829923}}
现在以后台任务启动相同函数:
(apsbits_env) blctrl@blctrl-s3:~$ qserver function execute '{"name": "function_sleep", "args": [60], "kwargs": {}}' background
Arguments: ['function', 'execute', '{"name": "function_sleep", "args": [60], "kwargs": {}}', 'background']
15:41:10 - MESSAGE:
{'success': True,
'msg': '',
'item': {'name': 'function_sleep',
'args': [60],
'kwargs': {},
'user': 'qserver-cli',
'user_group': 'primary',
'item_uid': 'b2b7f859-58ef-4c55-ae81-75fd4faf206d'},
'task_uid': 'b2b7f859-58ef-4c55-ae81-75fd4faf206d'}
并且检查状态:
(apsbits_env) blctrl@blctrl-s3:~$ qserver status
Arguments: ['status']
15:41:19 - MESSAGE:
{
'manager_state': 'idle',
'queue_stop_pending': False,
'queue_autostart_enabled': False,
'worker_environment_exists': True,
'worker_environment_state': 'idle',
'worker_background_tasks': 1,
现在,管理器和环境的状态均为 'idle',并且后台任务的数量为 1。可以像第一个示例中那样,使用任务 UID 来监控任务状态。无需等待第一个函数实例完成,即可再次启动该函数:
(apsbits_env) blctrl@blctrl-s3:~$ qserver function execute '{"name": "function_sleep", "args": [60], "kwargs": {}}' background
并且检查状态. 背景任务的数目现在是2:
(apsbits_env) blctrl@blctrl-s3:~$ qserver status
Arguments: ['status']
15:45:43 - MESSAGE:
{'...
'manager_state': 'idle',
'queue_stop_pending': False,
'queue_autostart_enabled': False,
'worker_environment_exists': True,
'worker_environment_state': 'idle',
'worker_background_tasks': 2,
're_state': 'idle',
管理器和环境的状态为 'idle',这意味着用户可以自由运行计划或前台任务,而无需等待后台任务完成。后台任务也可以在计划或前台任务运行时启动。尝试将函数作为前台任务运行。也可以尝试在函数运行时运行一个计划。还可以尝试在计划或前台任务运行时运行该函数的一个或多个副本。
上载脚本
RE Manager 为用户提供了在worker命名空间中上传和执行 Python 脚本的能力。更多详细说明请参见“上传脚本”一节。
qserver script upload CLI 工具支持'script_upload' API 的所有功能。它接受脚本文件的路径作为参数,而不是脚本的字符串表示形式。我们在当前目录下创建一个简单的脚本文件(例如 test_script.py):
# 添加一个简单的计划
def count_test(detectors, *, num=1, delay=1):
yield from count(detectors, num=num, delay=delay)
# 等待一段时间来模拟更长执行时间的脚本
ttime.sleep(30)
该脚本向环境中添加了一个名为 count_test 的新计划,然后等待 30 秒以模拟较长的执行时间。按照“计划的立即执行”中的步骤启动 RE Manager,打开环境,并验证 RE Manager 处于idle状态。然后检查该计划是否不在允许的计划列表中:
(apsbits_env) blctrl@blctrl-s3:~/pydir$ qserver allowed plans
Arguments: ['allowed', 'plans']
...
上传脚本到RE管理器:
(apsbits_env) blctrl@blctrl-s3:~/pydir$ qserver script upload script.py
Arguments: ['script', 'upload', 'script.py']
14:06:24 - MESSAGE:
{'success': True, 'msg': '', 'task_uid': 'bb58e939-84aa-4d69-8271-fd4f870c64de'}
...
当这个脚本运行时, 检查RE管理器状态。现在以'executing_task'返回管理器和环境状态:
(apsbits_env) blctrl@blctrl-s3:~/pydir$ qserver status
Arguments: ['status']
14:30:58 - MESSAGE:
{
...
'manager_state': 'executing_task',
'queue_stop_pending': False,
'queue_autostart_enabled': False,
'worker_environment_exists': True,
'worker_environment_state': 'executing_task',
}
通过检查任务状态(使用任务UID)确认任务正在运行:
(apsbits_env) blctrl@blctrl-s3:~/pydir$ qserver task status 'feb6792e-cecd-4af8-9e19-2543ecdd25fa'
Arguments: ['task', 'status', 'feb6792e-cecd-4af8-9e19-2543ecdd25fa']
14:35:20 - MESSAGE:
{'success': True,
'msg': '',
'task_uid': 'feb6792e-cecd-4af8-9e19-2543ecdd25fa',
'status': 'running'}
等待脚本执行结束. 再次检查状态:
(apsbits_env) blctrl@blctrl-s3:~/pydir$ qserver task status 'feb6792e-cecd-4af8-9e19-2543ecdd25fa'
Arguments: ['task', 'status', 'feb6792e-cecd-4af8-9e19-2543ecdd25fa']
14:36:40 - MESSAGE:
{'success': True,
'msg': '',
'task_uid': 'feb6792e-cecd-4af8-9e19-2543ecdd25fa',
'status': 'completed'}
查看执行的结果. 返回值总是None, 因为这个脚本没有返回任何值. 检查success时True, 而错误消息和回溯是空字符串:
(apsbits_env) blctrl@blctrl-s3:~/pydir$ qserver task result 'feb6792e-cecd-4af8-9e19-2543ecdd25fa'
Arguments: ['task', 'result', 'feb6792e-cecd-4af8-9e19-2543ecdd25fa']
14:38:23 - MESSAGE:
{'success': True,
'msg': '',
'task_uid': 'feb6792e-cecd-4af8-9e19-2543ecdd25fa',
'status': 'completed',
'result': {'task_uid': 'feb6792e-cecd-4af8-9e19-2543ecdd25fa',
'success': True,
'msg': '',
'traceback': '',
'return_value': None,
'time_start': 1777012502.2269387,
'time_stop': 1777012532.2759979}}
装载允许的计划的列表, 并且确认count_test在此列表中:
(apsbits_env) blctrl@blctrl-s3:~/pydir$ qserver allowed plans
Arguments: ['allowed', 'plans']
14:39:48 - MESSAGE:
{'success': True,
'msg': '',
'plans_allowed': {...,
'count_test': '{...}',
...}
'plans_allowed_uid': '56b985fa-f505-4ee3-b96c-b24cd8a95d12'}
现在计划count_test可以被放入队列并且由RE管理器执行.
队列自动启动模式
在自动启动模式下,如果队列非空且管理器和工作进程的状态允许执行计划,队列将自动开始执行。更多信息请参阅“队列自动启动模式”。按照“启动队列服务器”中的说明启动 RE Manager。
第一部分
确认队列和历史是空的并且自动启动模式被禁用:
(apsbits_env) blctrl@blctrl-s3:~/pydir$ qserver status
Arguments: ['status']
14:44:37 - MESSAGE:
{'msg': 'RE Manager v0.0.23',
'items_in_queue': 0,
'items_in_history': 19,
...}
(apsbits_env) blctrl@blctrl-s3:~/pydir$ qserver queue clear
(apsbits_env) blctrl@blctrl-s3:~/pydir$ qserver history clear
(apsbits_env) blctrl@blctrl-s3:~/pydir$ qserver status
Arguments: ['status']
14:45:04 - MESSAGE:
{'msg': 'RE Manager v0.0.23',
'items_in_queue': 0,
'items_in_history': 0,
...
'queue_autostart_enabled': False,
'queue_autostart_enabled': False,
'worker_environment_exists': False,
...
}
打开环境:
(apsbits_env) blctrl@blctrl-s3:~/pydir$ qserver environment open
启用自动启动模式:
(apsbits_env) blctrl@blctrl-s3:~/pydir$ qserver queue autostart enable
Arguments: ['queue', 'autostart', 'enable']
14:49:38 - MESSAGE:
{'success': True, 'msg': ''}
检查自动启动模式被启用:
(apsbits_env) blctrl@blctrl-s3:~/pydir$ qserver status
Arguments: ['status']
14:49:46 - MESSAGE:
{...
'queue_autostart_enabled': True,
}
添加一个计划到队列:
$ qserver queue add plan '{"name": "count", "args": [["det1", "det2"]], "kwargs": {"num": 10, "delay": 1}}'
观察到计划的执行自动开始了。请检查状态,以确保已执行的计划已被添加到计划历史中,并且自动启动模式仍处于开启状态:
(apsbits_env) blctrl@blctrl-s3:~/pydir$ qserver status
Arguments: ['status']
14:54:03 - MESSAGE:
{'msg': 'RE Manager v0.0.23',
'items_in_queue': 0,
'items_in_history': 1,
'running_item_uid': 'ecd52e9d-14bd-4899-9dd8-39064b528438',
'manager_state': 'executing_queue',
'queue_stop_pending': False,
'queue_autostart_enabled': True,
'worker_environment_exists': True,
'worker_environment_state': 'executing_plan',
'worker_background_tasks': 0,
're_state': 'running',
...
}
关闭环境:
$ qserver environment close
第二部分
只要队列停止(通过“queue_stop” API或queue_stop指令)、当前正在运行的计划被停止、中止或中断,或者当前计划失败(除非启用了忽略失败的队列模式,参见“queue_mode_set” API),自动启动模式就会自动禁用。
验证队列仍然处于自动模式:
(apsbits_env) blctrl@blctrl-s3:~$ qserver status
Arguments: ['status']
11:33:26 - MESSAGE:
{...
'queue_autostart_enabled': True,
...
}
环境仍然是关闭的。添加两个计划到这个队列:
(apsbits_env) blctrl@blctrl-s3:~$ qserver queue add plan '{"name": "count", "args": [["det1", "det2"]], "kwargs": {"num": 10, "delay": 2}}'
(apsbits_env) blctrl@blctrl-s3:~$ qserver queue add plan '{"name": "count", "args": [["det1", "det2"]], "kwargs": {"num": 10, "delay": 2}}'
现在打开环境:
(apsbits_env) blctrl@blctrl-s3:~$ qserver environment open
观察到管理器自动启动这个队列. 在第一个计划仍在运行时, 发送站厅接着停止这个计划的请求:
(apsbits_env) blctrl@blctrl-s3:~$ qserver re pause
(apsbits_env) blctrl@blctrl-s3:~$ qserver re stop
观察到RE管理器调试输出确认了计划停止了. 现在检查状态来确认一个计划仍在队列中并且自动启动模式被禁用了:
(apsbits_env) blctrl@blctrl-s3:~$ qserver status
Arguments: ['status']
11:36:48 - MESSAGE:
{'msg': 'RE Manager v0.0.23',
'items_in_queue': 1,
...
'queue_autostart_enabled': False,
}
在IPython模式中启动队列服务器
队列服务器可配置为在 IPython 内核中运行工作环境。在此模式下,工作进程可接受包含 IPython 特有功能(例如魔术命令、user_ns 等)的启动代码和上传脚本。用户还可以直接使用 Jupyter Console 连接到该内核,交互式地执行计划和运行 IPython 命令。这样可以实现双工作流:既支持基于 API 控制典型计划的执行(例如用于提供用户友好的图形界面),又允许专家用户通过交互式 IPython 访问环境。
有关 IPython 模式的更多信息,请参阅《在运行 RE Worker 时使用 IPython 内核》一文。
可以通过参数 --use-ipython-kernel=ON 以 IPython 模式启动RE Manager。
$ start-re-manager --use-ipython-kernel=ON
默认, IPython内核使用agg matplotlib后端, 此后端阻止Matplotlib绘图被显示。要启用绘图, 使用--ipython-matplotlib参数传递一个不同的后端:
(apsbits_env) blctrl@blctrl-s3:~$ start-re-manager --use-ipython-kernel=ON --ipython-matplotlib=qt5
现在启动 RE Manager(无论是否设置 Matplotlib 后端),然后打开环境:
(apsbits_env) blctrl@blctrl-s3:~$ qserver environment open
RE管理器的调试输出将包含以下:
...
[I 2026-04-27 11:57:55,366 bluesky_queueserver.manager.worker] Initializing IPython kernel ...
...
Loading file '/tmp/qserver_blctrl/ipython/profile_collection_sim/startup/00-ophyd.py'
Loading file '/tmp/qserver_blctrl/ipython/profile_collection_sim/startup/05-run-engine.py'
Loading file '/tmp/qserver_blctrl/ipython/profile_collection_sim/startup/15-plans.py'
Loading file '/tmp/qserver_blctrl/ipython/profile_collection_sim/startup/99-custom.py'
[I 2026-04-27 11:57:56,592 bluesky_queueserver.manager.worker] IPython kernel initialization is complete.
[I 2026-04-27 11:57:56,795 bluesky_queueserver.manager.worker] IPython kernel connection info:
{'transport': 'tcp',
'ip': '127.0.0.1',
'shell_port': 50265,
'iopub_port': 35559,
'stdin_port': 45801,
'hb_port': 51765,
'control_port': 57113,
'signature_scheme': 'hmac-sha256',
'key': '68f9817d-b93a3d4df6d9bcaf08beaf18'}
检查RE管理器状态:
(apsbits_env) blctrl@blctrl-s3:~$ qserver status
Arguments: ['status']
12:35:16 - MESSAGE:
{...
'ip_kernel_state': 'idle',
'ip_kernel_captured': False,
...}
内核处于“空闲”状态,已准备好执行任务,参数 ip_kernel_captured 指示内核是否正在执行由 RE Manager 启动的前台任务(计划、函数或脚本)。
将计划添加到队列中并启动队列:
(apsbits_env) blctrl@blctrl-s3:~$ qserver queue add plan '{"name": "count", "args": [["det1", "det2"]], "kwargs": {"num": 10, "delay": 1}}'
(apsbits_env) blctrl@blctrl-s3:~$ qserver queue start
当计划正在运行时, 检查状态. 内核状态现在是busy并且内核被RE管理器捕获.
(apsbits_env) blctrl@blctrl-s3:~$ qserver status
Arguments: ['status']
12:53:18 - MESSAGE:
{...
're_state': 'running',
'ip_kernel_state': 'busy',
'ip_kernel_captured': True,
...
}
现在打开另一个终端并且使用Jupyter Console连接内核. qserver-console CLI工具从RE管理器下载当前内核连接信息并且传递它给Jupyter Console:
(apsbits_env) blctrl@blctrl-s3:~/Desktop$ qserver-console
...
In [1]:
另外, qserver-qtconsole用于启动Jupyter Qt Console:
$ qserver-qtconsole
在IPython提示中输入一个计划:
In [1]: RE(count([det1,det2],num=10, delay=2))
当计划在 Jupyter Console 中执行时,其输出也会显示在 RE Manager 的控制台输出中。在计划运行期间可以关闭 Jupyter Console(先按 Ctrl-C,再按 Ctrl-D),但计划会继续在内核中运行。在计划运行期间检查状态:
(apsbits_env) blctrl@blctrl-s3:~$ qserver status
Arguments: ['status']
13:14:47 - MESSAGE:
{...
're_state': 'running',
'ip_kernel_state': 'busy',
'ip_kernel_captured': False,
...
}
内核状态为“忙”,但并未被管理器“捕获”。在控制台启动的任务完成且内核变为空闲状态之前,RE Manager 无法开始执行前台任务(计划/函数/脚本)。
注意: 使用Ctrl-D退出Jupyter Console: 输入quit或exit将各自退出和关闭内核和工作进程环境.
关闭环境:
$ qserver environment close
只有当内核处于空闲状态时,才能关闭环境。销毁环境的操作会终止工作进程,并相应地终止内核,无论内核处于何种状态。
IPython模式: 中断内核
目前还无法通过 Jupyter Console(按 Ctrl-C)向内核发送中断信号。本教程演示了如何使用 re_pause API 暂停计划,或使用 kernel_interrupt API 中断任务。虽然可以通过发送一次或两次 kernel_interrupt API 请求来暂停计划,但建议使用 re_pause API。
本教程演示了如何使用命令行发起中断,但这在实际生产部署中并不实用。通常假设会通过 GUI 组件来方便地调用 API。
以 IPython 模式启动 RE Manager:
$ start-re-manager --use-ipython-kernel=ON --ipython-matplotlib=qt5
打开单独一个终端用于执行qserver命令以及打开环境:
$ qserver environment open
在单独一个终端中启动Jupyter Console:
$ qserver-console
A. 暂停计划
在console中启动一个计划:
(apsbits_env) blctrl@blctrl-s3:~$ qserver re pause
当计划在console中运行时, 使用're_pause' API暂停这个计划:
(apsbits_env) blctrl@blctrl-s3:~$ qserver re pause
Arguments: ['re', 'pause']
13:27:12 - MESSAGE:
{'success': True, 'msg': ''}
观察在Jupyter Console中计划输出, 确认此计划被暂停. 检查状态:
(apsbits_env) blctrl@blctrl-s3:~$ qserver status
Arguments: ['status']
13:29:35 - MESSAGE:
{
'items_in_queue': 0,
'manager_state': 'idle',
'queue_stop_pending': False,
'queue_autostart_enabled': False,
'worker_environment_exists': True,
'worker_environment_state': 'idle',
'worker_background_tasks': 0,
're_state': 'paused',
'ip_kernel_state': 'idle',
'ip_kernel_captured': False,
}
请注意,此时 RE Manager 和工作环境的状态均为“空闲”,因此 RE Manager 并不知晓计划已被暂停。现在在 Jupyter 控制台中恢复计划,并让它运行至完成:
In [5]: RE.resume()
B. 发送中断(Ctrl-C)
在Jupyter Console中, 启动一个长运行的任务:
In [6]: for n in range(30):
...: print(f"n = {n}")
...: ttime.sleep(1)
...:
从终端发送请求'kernel_interrput' API:
(apsbits_env) blctrl@blctrl-s3:~$ qserver kernel interrupt
Arguments: ['kernel', 'interrupt']
13:35:50 - MESSAGE:
{'success': True, 'msg': ''}
观察在Jupyter Console中的输出, 确认任务被终端了:
In [6]: for n in range(30):
...: print(f"n = {n}")
...: ttime.sleep(1)
...:
n = 0
n = 1
n = 2
n = 3
n = 4
n = 5
n = 6
n = 7
n = 8
n = 9
n = 10
---------------------------------------------------------------------------
KeyboardInterrupt Traceback (most recent call last)
Cell In[6], line 3
1 for n in range(30):
2 print(f"n = {n}")
----> 3 ttime.sleep(1)
KeyboardInterrupt:
关闭环境:
$ qserver environment close
IPython模式: 更新环境
用户可以通过 Jupyter Console 直接连接到 IPython 内核,从而在工作进程命名空间中添加、删除或修改计划和设备。RE Manager 并不会立即感知到命名空间的变化。为了使新增或修改后的计划、设备能够对客户端应用程序可见,可以使用 environment_update API 来更新现有/允许的计划和设备列表。
用IPython模式启动RE管理器:
$ start-re-manager --use-ipython-kernel=ON --ipython-matplotlib=qt5
打开单独一个终端, 用于执行qserver命令和打开环境:
$ qserver environment open
在单独一个终端中启动Jupyter Console:
$ qserver-console
在Jupyter Console中添加一个新计划:
In [1]: def my_plan():
...: yield from bps.sleep(1)
...:
在终端中, 检查可用计划的列表. 计划my_plan不在此列表中:
(apsbits_env) blctrl@blctrl-s3:~$ qserver allowed plans
现在通过发送'environment_update' API请求更新这个环境:
(apsbits_env) blctrl@blctrl-s3:~$ qserver environment update
Arguments: ['environment', 'update']
13:48:12 - MESSAGE:
{'success': True, 'msg': '', 'task_uid': '01d3b9b5-e197-4176-8860-b64541ef7d35'}
(apsbits_env) blctrl@blctrl-s3:~$ qserver allowed plans
Arguments: ['allowed', 'plans']
13:48:22 - MESSAGE:
{'success': True,
'msg': '',
'plans_allowed': {...
'my_plan': '{...}',
...},
'plans_allowed_uid': '60852235-9244-4f14-85ba-b49127593a24'}
现在plans_allowd_uid更改了并且my_plan计划现在在列表中了.
关闭环境:
$ qserver environment close
锁定RE管理器
用户可以通过“密钥”临时锁定 RE Manager。用户需要记住(或保存)该密钥,并在安全时解锁管理器。用户可以选择锁定工作环境和/或队列,从而防止其他用户在未被提供密钥的情况下更改环境状态(如启动队列、运行计划、上传脚本等)或队列状态(如添加、编辑或重新排序队列中的计划等)。有关更详细的描述,请参阅《锁定 RE Manager》部分。
请按照《启动队列服务器》中给出的说明启动 RE Manager。
检查RE管理器的状态:
(apsbits_env) blctrl@blctrl-s3:~$ qserver status
Arguments: ['status']
13:54:45 - MESSAGE:
{..
'lock_info_uid': 'e5dcca3b-81fe-4e65-a1c4-c67b67ea54d3',
'lock': {'environment': False, 'queue': False}}
锁参数指示环境和队列是否被锁定,每次锁状态变更时 lock_info_uid 都会更新,供监控客户端应用程序使用。
加载锁状态:
(apsbits_env) blctrl@blctrl-s3:~$ qserver lock info
Arguments: ['lock', 'info']
13:58:54 - MESSAGE:
{'success': True,
'msg': '',
'lock_info': {'environment': False,
'queue': False,
'user': None,
'time': None,
'time_str': '',
'note': None,
'emergency_lock_key_is_set': False},
'lock_info_uid': 'e5dcca3b-81fe-4e65-a1c4-c67b67ea54d3'}
当管理器被锁定时,状态信息中包含施加锁的用户名(user)、施加锁的时间(time、time_str),以及可选的备注(note),用于向系统中的其他用户解释锁定的原因。参数 emergency_lock_key_is_set(值为 False)表示应急密钥尚未设置,只有使用锁定时的原密钥才能解锁管理器。
添加备注来锁定环境:
(apsbits_env) blctrl@blctrl-s3:~$ qserver --lock-key userlockkey lock environment "The environment is locked. Do not unlock environment!" Arguments: ['lock', 'environment', 'The environment is locked. Do not unlock environment!']
09:30:55 - MESSAGE:
{'success': True,
'msg': '',
'lock_info': {'environment': True,
'queue': False,
'user': 'qserver-cli',
'time': 1777339855.4604006,
'time_str': '04/28/2026 09:30:55',
'note': 'The environment is locked. Do not unlock environment!',
'emergency_lock_key_is_set': False},
'lock_info_uid': 'd177bd17-8653-4d4e-834d-15432b9e3c58'}
锁键可以由锁定管理器的用户任意选择(在本例中,该键为 userlockkey)。参数 user、time、time_str 和 note 现已正确设置,参数 environment 为 True。
qserver_lock_info可用于验证锁键。如果在没有锁键的情况下调用,该调用始终成功。如果管理器被锁定,则会验证所包含的键,并且仅当键有效时调用才会成功。尝试验证无效的键:
(apsbits_env) blctrl@blctrl-s3:~$ qserver --lock-key someinvalidkey lock info
Arguments: ['lock', 'info']
09:37:54 - MESSAGE:
{'success': False,
'msg': 'Error: Invalid lock key: \n'
'RE Manager is locked by qserver-cli at 04/28/2026 09:30:55\n'
'Environment is locked: True\n'
'Queue is locked: False\n'
'Emergency lock key: not set\n'
'Note: The environment is locked. Do not unlock environment!',
'lock_info': {'environment': True,
'queue': False,
'user': 'qserver-cli',
'time': 1777339855.4604006,
'time_str': '04/28/2026 09:30:55',
'note': 'The environment is locked. Do not unlock environment!',
'emergency_lock_key_is_set': False},
'lock_info_uid': 'd177bd17-8653-4d4e-834d-15432b9e3c58'}
调用失败('success':False)并且错误消息表明锁键是无效的. 尝试验证有效键:
apsbits_env) blctrl@blctrl-s3:~$ qserver --lock-key userlockkey lock info
Arguments: ['lock', 'info']
09:40:05 - MESSAGE:
{'success': True,
'msg': '',
'lock_info': {'environment': True,
'queue': False,
'user': 'qserver-cli',
'time': 1777339855.4604006,
'time_str': '04/28/2026 09:30:55',
'note': 'The environment is locked. Do not unlock environment!',
'emergency_lock_key_is_set': False},
'lock_info_uid': 'd177bd17-8653-4d4e-834d-15432b9e3c58'}
由于环境已被锁定,所有会改变环境状态的操作(例如打开和关闭环境、启动队列等)只有在调用中包含有效锁键时才能执行。尝试在不带锁键的情况下打开环境:
(apsbits_env) blctrl@blctrl-s3:~$ qserver environment open
Arguments: ['environment', 'open']
09:43:09 - MESSAGE:
{'success': False,
'msg': 'Error: Invalid lock key: \n'
'RE Manager is locked by qserver-cli at 04/28/2026 09:30:55\n'
'Environment is locked: True\n'
'Queue is locked: False\n'
'Emergency lock key: not set\n'
'Note: The environment is locked. Do not unlock environment!'}
现在尝试用锁键打开环境:
(apsbits_env) blctrl@blctrl-s3:~$ qserver --lock-key userlockkey environment open
Arguments: ['environment', 'open']
09:44:43 - MESSAGE:
{'success': True, 'msg': ''}
操作成功. 现在用锁键关闭环境:
(apsbits_env) blctrl@blctrl-s3:~$ qserver --lock-key userlockkey environment close
Arguments: ['environment', 'close']
09:44:38 - MESSAGE:
{'success': True, 'msg': ''}
qserver_lock也允许锁定队列(阻塞对队列操作的访问)或者同时环境和队列. 尝试锁定队列(可选地添加备注):
(apsbits_env) blctrl@blctrl-s3:~$ qserver --lock-key userlockkey lock queue
Arguments: ['lock', 'queue']
09:47:45 - MESSAGE:
{'success': True,
'msg': '',
'lock_info': {'environment': False,
'queue': True,
'user': 'qserver-cli',
'time': 1777340865.2197852,
'time_str': '04/28/2026 09:47:45',
'note': None,
'emergency_lock_key_is_set': False},
'lock_info_uid': '367d0f33-7cde-4da5-89f4-ddcb55abfbd5'}
并且接着带和不带--lock-key参数地添加计划到队列, 接着锁定环境和队列:
(apsbits_env) blctrl@blctrl-s3:~$ qserver --lock-key userlockkey lock all
Arguments: ['lock', 'all']
09:48:12 - MESSAGE:
{'success': True,
'msg': '',
'lock_info': {'environment': True,
'queue': True,
'user': 'qserver-cli',
'time': 1777340892.9305968,
'time_str': '04/28/2026 09:48:12',
'note': None,
'emergency_lock_key_is_set': False},
'lock_info_uid': '0e437a07-8970-471a-9cef-327ba338810c'}
只要传递了有效的锁键,就可以重复对已锁定的管理器应用锁操作以更改锁定选项。未解锁管理器的情况下,无法更改锁键。
要解锁管理器,请使用有效的锁键运行 qserver unlock:
(apsbits_env) blctrl@blctrl-s3:~$ qserver --lock-key userlockkey unlock
Arguments: ['unlock']
09:52:30 - MESSAGE:
{'success': True,
'msg': '',
'lock_info': {'environment': False,
'queue': False,
'user': None,
'time': None,
'time_str': '',
'note': None,
'emergency_lock_key_is_set': False},
'lock_info_uid': '7bd8224e-0052-437b-95dc-b7fcf7d514f5'}
锁状态存储在Redis中并且在会话之间存在, 即, 重启RE管理器不会清除锁. 如果锁丢失了, 则使用一个可选地紧急锁键可以解锁管理器:
# 用紧急锁键启动RE管理器
QSERVER_EMERGENCY_LOCK_KEY_FOR_SERVER=emlockkey start-re-manager
# 锁住环境
$ qserver --lock-key key-to-forget lock environment
# 假设键丢失了, 用紧急锁解锁管理器
$ qserver --lock-key emlockkey unlock
# 检查锁状态, 管理器应该被解锁了
$ qserver lock info
如果未设置应急键,则可以通过运行 qserver-clear-lock 命令行工具,然后重启 RE Manager 服务或应用程序来清除锁。该工具需要能够访问 RE Manager 所使用的 Redis 服务器。以下步骤说明了该过程:
# 启动RE管理器
# 锁定环境
$ qserver --lock-key key-to-forget lock environment
# 检查锁状态
$ qserver lock info
# 假设锁丢失了. 清除在Redis中的锁, 如果需要, 传递'--redis-addr'
qserver-clear-lock
# 停止和重启RE管理器程序
# 检查锁状态, 管理器应该被解锁了
$ qserver lock info
更改用户组权限
RE 管理器提供了'permissions_get'和'permissions_set' API,允许客户端下载和上传用户组权限。Python API 操作以字典形式表示的权限,可以下载、修改后再上传至管理器。一旦带有权限的字典被上传,管理器会更新允许的计划和设备列表以反映新的权限。但该 API 的 qserver 命令行实现不够灵活:qserver permissions get 会加载并打印权限字典,而 qserver permissions set 接受包含新用户组权限的 YAML 文件路径,因此目前通过命令行难以轻松完成简单的“加载-修改-上传”操作。
按照“启动队列服务器”中给出的说明启动 RE 管理器。
加载并检查允许的计划列表。确保 grid_scan 在该列表中:
(apsbits_env) blctrl@blctrl-s3:~$ qserver allowed plans
Arguments: ['allowed', 'plans']
10:08:13 - MESSAGE:
{'success': True,
'msg': '',
'plans_allowed': {'...
'grid_scan': '{...}',
'rel_adaptive_scan': '{...}',
...},
'plans_allowed_uid': '274c3990-dee5-4ebf-8c91-742d4d226c15'}
装载和检查主用户组的权限: 允许用户执行所有计划:
(apsbits_env) blctrl@blctrl-s3:~$ qserver permissions get
Arguments: ['permissions', 'get']
10:10:58 - MESSAGE:
{'success': True,
'msg': '',
'user_group_permissions': {'user_groups': {...
'primary': {'allowed_plans': [':.*'],
'forbidden_plans': [None],
'allowed_devices': [':?.*:depth=5'],
'forbidden_devices': [None],
'allowed_functions': ['function_sleep',
':^func_for_test']},
...
}
我们来创建一个 YAML 文件(例如 new_permissions.yaml),其中包含修改后的用户组权限,用于禁止用户将 grid_scan 计划添加到队列中(root 用户组定义了应用于所有其他组的权限,必须始终存在于权限字典中):
user_groups:
root: # 此组包含所有可用计划和设备
allowed_plans:
- null # 允许所有
forbidden_plans:
- ":^_" # 名称以'_'开头的所有计划
allowed_devices:
- null # 允许所有
forbidden_devices:
- ":^_:?.*" # 名称以'_'开头的所有设备
allowed_functions:
- null # 允许所有
forbidden_functions:
- ":^_" # 名称以'_'开头的所有函数
primary: # 词组包含束线工作人员, 包含所有或者大部分计划和设备
allowed_plans:
- ":.*" # 允许所有计划的不同方式
forbidden_plans:
- "grid_scan"
allowed_devices:
- ":?.*:depth=5" # 允许所有设备和子设备. 子设备最大深度为5.
forbidden_devices:
- null # 无禁止
allowed_functions:
- "function_sleep" # 显式列出的名称
上传权限给RE管理器:
(apsbits_env) blctrl@blctrl-s3:~/pydir$ qserver permissions set new_permissions.yaml
Arguments: ['permissions', 'set', 'new_permissions.yaml']
10:24:56 - MESSAGE:
{'success': True, 'msg': ''}
再次下载权限来验证权限被修改了:
(apsbits_env) blctrl@blctrl-s3:~/pydir$ qserver permissions get
Arguments: ['permissions', 'get']
10:25:14 - MESSAGE:
{'success': True,
'msg': '',
'user_group_permissions': {'user_groups': {'root': {'allowed_plans': [None],
'forbidden_plans': [':^_'],
'allowed_devices': [None],
'forbidden_devices': [':^_:?.*'],
'allowed_functions': [None],
'forbidden_functions': [':^_']},
'primary': {'allowed_plans': [':.*'],
'forbidden_plans': ['grid_scan'],
'allowed_devices': [':?.*:depth=5'],
'forbidden_devices': [None],
'allowed_functions': ['function_sleep']}}}}
检查grid_scan不在可用计划列表中
$ qserver allowed plans
用自定义启动代码运行RE管理器
本部分的所有教程均使用一组内置启动脚本,这些脚本提供模拟设备和简单计划,足以探索队列服务器的功能。任何实际应用都需要使用自定义启动脚本来启动服务器,这些脚本需包含代表真实硬件的 Ophyd 设备以及执行有效测量的 Bluesky 计划。本教程将说明如何配置服务器以加载自定义的 IPython 风格启动脚本。
我们不会创建新脚本,而是将现有的启动文件复制到自定义目录中,并配置服务器从该目录加载脚本。之后可以修改这些脚本或用自定义脚本替换它们。
- 第一步: 在方便的位置为启动文件创建一个目录,例如 ~/qs_startup。该目录应对运行 RE 管理器的用户具有可读和可写权限。
- 第二步: 将仓库中的启动脚本(仅 .py 文件)和 user_group_permissions.yaml 复制到 ~/qs_startup。existing_plans_and_devices.yaml 文件将在教程过程中由 RE Manager 生成,因此不要复制它。该目录应包含以下文件:
(apsbits_env) blctrl@blctrl-s3:~/qs_startup$ ls
00-ophyd.py 15-plans.py 99-custom.py user_group_permissions.yaml
- 第三步: 通过指定启动目录的路径启动RE管理器:
(apsbits_env) blctrl@blctrl-s3:~$ start-re-manager --startup-dir ~/qs_startup
- 第四步: 打开RE Woker环境:
(apsbits_env) blctrl@blctrl-s3:~/qs_startup$ qserver environment open
Arguments: ['environment', 'open']
10:54:03 - MESSAGE:
{'success': True, 'msg': ''}
第五步: 验证产生了文件existing_plans_and_devices.yaml:
(apsbits_env) blctrl@blctrl-s3:~/qs_startup$ ls
00-ophyd.py 99-custom.py user_group_permissions.yaml
15-plans.py existing_plans_and_devices.yaml
RE Manager 已准备就绪,可以将计划提交到队列并执行。如果添加或修改了计划或设备,则必须关闭当前打开的环境并重新打开,以重新加载启动文件并生成新的现有计划和设备列表。
在某些配置中,将启动文件放置在某个 IPython 配置文件的启动目录中会很方便,这样它们就可以加载到 IPython 中。在 NSLS‑II,通常使用名为 collection 的 IPython 配置文件来运行 Bluesky 软件,启动文件的标准位置是 ~/.ipython/profile_collection/startup。可以通过显式指定目录来配置 RE Manager 以查找启动文件:
$ start-re-manager --startup-dir ~/.ipython/profile_collection/startup
或者通过指定IPython配置文件的名称:
$ start-re-manager --startup-profile collection
除了支持 IPython 风格的启动脚本集外,RE Manager 还可以配置为从 Python 脚本(通过指定脚本文件路径)或从已安装的 Python 模块加载代码。相关配置说明请参阅“使用配置文件”一节。请注意,加载 IPython 风格启动脚本的代码会进行补丁处理,以提供与 IPython 某些功能的兼容性。实现补丁主要是为了简化从束线站上常用的 IPython 工作流程的过渡。启动脚本的编写假定为是在纯 Python 环境中执行,因此不会进行补丁处理。理想情况下,当由队列服务器执行时,所有使用 IPython 特性的代码块都应被禁用(请参阅“检测代码是否由 RE Worker 执行”)。
手动生成已有计划和设备列表
当 RE Worker 环境打开时,RE管理器会自动生成或更新现有计划和设备列表,但在某些情况下手动生成该列表会更加方便。例如,当开发人员修改了 profile_collection_sim 目录中的相应启动文件后,希望更新该目录下的 existing_plans_and_devices.yaml 文件时,只能手动操作(RE Manager 设计为不会自动修改内置的 profile_collection_sim 目录中的文件)。
- 步骤 1. 如“使用自定义启动代码运行 RE管理器”一节所述,创建包含启动文件的目录并复制启动 Python 文件。我们假设这些文件位于目录 ~/qt_startup 中。该目录应包含以下文件:
(apsbits_env) blctrl@blctrl-s3:~/qs_startup$ ls
00-ophyd.py 15-plans.py 99-custom.py user_group_permissions.yaml
- 步骤2. 使用qserver-list-plans-devices CLI工具产生existing_plans_and_devices.yaml:
(apsbits_env) blctrl@blctrl-s3:~$ qserver-list-plans-devices --startup-dir ~/qs_startup --file-dir ~/qs_startup INFO:bluesky_queueserver.manager.profile_ops:Loading RE Worker startup code from directory '/home/blctrl/qs_startup' ...
INFO:bluesky_queueserver.manager.profile_ops:Startup directory: '/home/blctrl/qs_startup'
INFO:bluesky_queueserver.manager.profile_ops:Loading startup file '/home/blctrl/qs_startup/00-ophyd.py' ...
Loading file '/home/blctrl/qs_startup/00-ophyd.py'
INFO:bluesky_queueserver.manager.profile_ops:Loading startup file '/home/blctrl/qs_startup/15-plans.py' ...
Loading file '/home/blctrl/qs_startup/15-plans.py'
INFO:bluesky_queueserver.manager.profile_ops:Loading startup file '/home/blctrl/qs_startup/99-custom.py' ...
Loading file '/home/blctrl/qs_startup/99-custom.py'
The list of existing plans and devices was created successfully.
- 步骤3: 检查在这个目录下是否创建了文件
(apsbits_env) blctrl@blctrl-s3:~$ ls qs_startup/
00-ophyd.py 15-plans.py 99-custom.py existing_plans_and_devices.yaml user_group_permissions.yaml
此外, 可以从~/qs_startup目录启动qserver-list-plans-devices:
$ cd ~/qs_startup
$ qserver-list-plans-devices --startup-dir .
队列服务器提供了一个简单的 qserver-console-monitor 命令行工具,用于远程监控 RE管理器的控制台输出。该工具订阅 RE管理器通过 0MQ 发布的消息,并显示消息中的文本内容。qserver-console-monitor 的输出应与 RE Manager 自身的输出一致。此外,还可以选择禁用RE管理器控制台输出的打印功能,转而使用外部监控应用程序来可视化 RE管理器的输出。
在终端1, 启动qserver-console-monitor:
(apsbits_env) blctrl@blctrl-s3:~$ qserver-console-monitor
INFO:bluesky_queueserver.manager.output_streaming:Subscribing to console output stream fro m 0MQ address: tcp://localhost:60625 ...
INFO:bluesky_queueserver.manager.output_streaming:Subscribing to 0MQ topic: 'QS_Console' . ..
在终端2中, 使用控制台输出发布可用启动RE管理器:
(apsbits_env) blctrl@blctrl-s3:~$ start-re-manager --zmq-publish-console ON
打开终端 3,使用 qserver 工具运行一些命令。终端 1 和终端 2 必须显示相同的输出。可以同时运行多个 qserver-console-monitor 实例,它们会显示相同的控制台输出。尝试关闭(按 Ctrl-C)并重新启动 qserver-console-monitor。注意,当监控工具关闭时,所有已发布的控制台输出都会丢失。
在终端2中, 关闭RE管理器(Ctrl-C)并且用禁用控制台输出的打印功能重启它:
(apsbits_env) blctrl@blctrl-s3:~$ start-re-manager --zmq-publish-console ON --console-output OFF
请注意,终端 2 中没有打印任何输出。需要使用外部监控(在终端 1 中运行)来显示RE管理器的输出。
在实际应用中,客户端应用程序应实现订阅已发布的 RE管理器输出并将其展示给用户的功能。qserver-console-monitor 工具的使用应仅限于使用 RE管理器的系统的评估、测试和调试。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐
所有评论(0)