作者在官网提供了详细的解释,原文地址: http://krpc.github.io/krpc/python/client.html 翻译时稍有修改,大量使用机翻,如有错误请在评论区或私信提醒我修改。
新版专栏编辑器做得很好,希望B站不要再做了。
以下正文。
Python 客户端
该客户端提供了与kRPC服务器互动的 Python 接口(API)
安装库文件
kRPC库文件可以在PyPI或Github下载。
PyPI链接: https://pypi.python.org/pypi/krpc
Github链接: https://github.com/krpc/krpc/releases
或使用pip命令安装:
连接到服务器
krpc.connect()
函数用于启动与服务器的连接。 函数返回一个连接对象(类型为 krpc.client.Client
),可以通过该对象与服务器进行交互。 以下示例连接到本地计算机上运行的服务器,查询其版本并打印:
该函数还接受指定要连接的地址和端口号的参数,以及游戏中 kRPC 窗口中显示的连接的可选描述性名称。 例如:
调用远程过程
kRPC 服务器提供客户端可以运行的过程。这些过程被安排在称为服务(services) 的分组中,以保持条理清晰。连接时,Python 客户端会询问服务器以获得其提供的程序,并动态创建类类型、方法、属性等来调用它们。
以下示例演示如何使用 Python 客户端调用远程过程。 它调用 SpaceCenter.active_vessel
来获取表示活动容器(类型为 SpaceCenter.Vessel
)的对象。 它设置飞船的名称,然后打印其高度:
SpaceCenter
服务提供的所有功能都可以通过 conn.space_center
访问。 要探索该服务提供的功能,可以从交互式终端使用 help()
函数。 例如,运行 help(conn.space_center)
会列出 SpaceCenter
服务提供的所有类、枚举、过程和属性。 这对于类类型的工作原理类似,例如:help(conn.space_center.Vessel)
。
从服务器流式传输数据
kRPC 的常见用例是从游戏中持续提取数据。要做到这一点,最简单的方法就是重复调用一个远程存储过程,例如下面这个重复打印当前飞船位置的存储过程:
由于请求/响应消息在客户端和服务器之间重复发送,因此这种方法需要大量的通信开销。 kRPC 提供了一种更有效的机制来实现这一点,称为数据流(stream)。
数据流在服务器上(使用一组固定的参数值)重复执行一个过程,并将结果发送到客户端。只需向服务器发送一条信息即可建立数据流,接下来服务器将持续向客户端发送数据,直至数据流关闭。
下面的示例使用数据流实现与前例相同的操作:
在程序开始时调用一次 krpc.client.Client.add_stream()
来创建数据流,然后重复打印数据流返回的位置。 当客户端断开连接时,数据流会自动关闭。也可以使用 with
语句创建数据流,该语句可确保数据流在离开代码块后被关闭:
可以为任何返回值的过程创建流。 这包括方法调用和属性访问。 上面的示例演示了数据流方法的调用。 属性可以按如下方式进行数据流传输:
可以为任何函数调用创建数据流(属性设置除外)。调用 krpc.stream.Stream.__call__()
可以获得数据流的最新值。在数据流对象上调用 krpc.stream.Stream.remove()
可以停止数据流并将其从服务器上删除。断开连接时,所有客户端数据流都会自动停止。
同步更新数据流
kRPC 的一个常见用例是等待方法或属性返回的值发生变化,然后采取某些行动。kRPC 提供了两种有效的机制:条件变量(condition variabel)和回调(callback)。
条件变量
每个数据流都有一个与之关联的条件变量,每当数据流的值发生变化时,该变量就会收到通知。条件变量是 Python 标准库中 threading.Condition
的实例。这些变量可用于阻塞当前的执行线程,直到数据流的值发生变化。
下面的示例通过等待 vessel.control.abort
的值变为 true,一直等待直到游戏中的终止按钮被按下:
这段代码创建了一个数据流,获取数据流条件变量锁定(使用 with
语句),然后重复检测 abort
的值。当 abort
的值变为 true 时,它就会退出循环。
循环主体调用数据流上的 with
,这会导致程序阻塞,直到 abort
值发生变化。这可以防止循环 “旋转”(spinning),因此程序在等待时不会消耗处理资源。
注:在第一次调用 wait
之前,数据流不会开始接收更新。这意味着示例代码不会错过数据流数值的任何更新,因为它在收到第一次数据流更新之前就已经锁定了条件变量。
下面的示例代码使用 with
语句获取条件变量锁。也可以使用 acquire
和 release
来显式完成:
回调
数据流允许注册回调函数,当数据流的值发生变化时,该函数就会被调用。回调函数只需接收一个参数,即数据流的新值,且不返回任何内容。例如,如下程序注册两个回调,当 vessel.conrol.abort
的值发生变化时就会调用这两个回调:
注:创建数据流后,在调用 start
之前,它不会开始接收更新。在访问数据流的值时会隐式调用 start
,但由于本示例没有这样做,因此需要显式调用启动。
注:回调在调用 start
之前注册,这样就不会错过数据流更新。
注:调用回调函数的线程可能与创建流的线程不同。因此,对共享状态的任何更改都必须通过适当的同步来保护。
自定义事件
某些程序会返回krpc.event.Event
类型的事件对象。通过调用 krpc.event.Event.wait
,可以等待事件发生。在程序底层,这些都是使用数据流和条件变量实现的。
还可以创建自定义事件。表达式接口 (Expression API) 允许您创建在服务器上运行的代码,这些代码可用于创建自定义事件。例如,下面创建了 mean_altitude > 1000
表达式,然后创建了一个事件,当表达式返回 true 时将触发该事件:
接口参考
此函数创建一个与 kRPC 服务器的连接。返回 krpc.client.Client
对象,通过该对象可以与服务器通信。
参数
-
name(str) – 连接的描述性名称。 该信息被传递到服务器并显示在游戏内服务器窗口中。
-
adress(str) – 要连接的服务器地址。可以是主机名,也可以是点分十进制表示的 IP 地址。默认为 “127.0.0.1”。
-
rpc_port(int) – RPC 服务器的端口号。默认为 50000。该端口号应与要连接的服务器的 RPC 端口号一致。
-
stream_port(int) – 流服务器的端口号。默认为 50001。该端口号应与要连接的服务器的流端口号一致。
该类提供了与服务器通信的接口。服务器提供的所有功能都是动态填充的。该类的实例可通过调用 krpc.connect()
获得。
-
add_stream(func, *args, **kwargs)
为调用了参数 args 和 kwargs 的函数 func 创建数据流。返回
krpc.stream.Stream
对象。 -
stream(func, *args, **kwargs)
允许使用
with
语句创建流,并在数据流超出作用域时自动从服务器中移除。要以数据流的函数应作为 func 传递,其参数作为 args 和 kwargs 传递。 -
stream_update_condition
条件变量(类型为
threading.Condition
),每当流更新处理完毕时都会收到通知。 -
wait_for_stream_update(timeout=None)
此方法会阻塞,直到数据流更新处理完毕或操作超时。在调用此方法前,必须锁定流更新条件变量。如果指定的超时不是 None,则应是一个浮点数,指定操作的超时(秒)。 -
add_stream_update_callback(callback)
添加一个回调函数,当数据流更新处理完毕时调用该函数。
注:调用回调函数的线程可能与创建数据流的线程不同。因此,对共享状态的任何更改都必须通过适当的同步来保护。
-
remove_callback(callback)
删除数据流更新回调函数。
-
get_call(func, *args, **kwargs)
将对带有参数 args 和 kwargs 的函数 func 的调用转换为消息对象。这允许将过程调用的描述传递给服务器,例如在构建自定义事件时。请参阅自定义事件(Custom Events)。
-
close()
停止服务器的链接。
-
krpc
基本 KRPC 服务,提供与服务器基本功能的交互。
返回类型:
krpc.client.KRPC
该类可访问 KRPC 服务提供的基本服务器功能。实例可通过调用 krpc.client.Client.krpc
获得。有关该类的完整文档,请参见 KRPC (http://krpc.github.io/krpc/python/api/krpc.html)。其中部分功能由 python 客户端内部使用(例如创建和删除数据流),因此无需在应用程序代码中直接使用。
该类表示数据流。请参阅 http://krpc.github.io/krpc/python/client.html#python-client-streams .
-
start(wait=True)
启动数据流。通过调用
krpc.client.Client.add_stream()
创建流后,在调用此方法之前不会开始向客户端发送更新。
如果 wait 为 true,该方法将阻塞,直到从服务器至少接收到一次更新。如果 wait 为 false,方法将启动数据流并立即返回。如果数据流中尚未包含数值,对__call__()
的后续调用可能会引发StreamError
异常。 -
rate
数据流的更新速率(赫兹)。设置为零时,更新速率不受限制。
-
__call__()
返回数据流的最新值。如果执行流的远程过程时抛出异常,调用此方法将重新抛出异常。如果没有收到来自服务器的更新,则会引发
StreamError
异常。如果数据流尚未启动,本方法会调用start(True)
来启动数据流,并等待至少收到一次更新。 -
condition
条件变量(
threading.Condition
类型),每当数据流的值发生变化时,它就会收到通知。 -
wait(timeout=None)
此方法会阻塞,直到数据流的值发生变化或操作超时。在调用此方法前,必须锁定数据流条件变量。如果指定的超时不是 None,则应是一个浮点数,指定操作的超时(以秒为单位)。
如果数据流尚未启动,该方法会调用
start(False)
来启动流(无需等待至少收到一次更新)。 -
add_callback(callback)
添加一个回调函数,在数据流的值发生变化时调用。回调函数应有一个参数,即数据流的新值。
注:调用回调函数的线程可能与创建流的线程不同。因此,对共享状态的任何更改都必须通过适当的同步来保护。
-
remove_callback(callback)
从数据流中移除回调函数。
-
remove()
从服务器中移除数据流。
该类表示事件。请参阅自定义事件(Custom Events)。它是 bool 类型流的包装,指示事件何时发生。
-
start()
开始事件(Event)。 创建事件时,在调用此方法之前,它不会从服务器接收更新。
-
condition
事件发生时通知的条件变量(类型为
threading.Condition
)。 -
wait(timeout=None)
此方法会阻塞,直到事件发生或操作超时。在调用此方法前,必须锁定事件条件变量。如果指定的超时不是 None,则应是一个浮点数,指定操作超时的秒数。如果事件尚未启动,该方法会调用
start()
来启动底层流。 -
add_callback(callback)
添加回调函数,在事件发生时调用。回调函数应为无参数函数。
-
remove_callback(callback)
从事件中移除回调函数。
-
remove()
从服务器中移除事件。
-
stream
返回事件的底层数据流。