我怎样才能使系统时间 运行 在 Python 中更快?

How can i make the system time run faster in Python?

我在不同的控制台中编写了一个涉及两个脚本的模拟 运行ning。这些脚本通过 websocket 相互发送消息。消息以定义的时间间隔发送并包含时间戳(目前我使用 datetime.utcnow)。现在,当我加速模拟时,datetime 时间戳自然不受此影响,这意味着它们与模拟时间不同步。有没有办法“加快”系统时间,或者我是否必须编写自己的时间戳函数来确定速度?

编辑: 由于我无法更改系统时间,因此我编写了一个脚本,其中包含一个 运行s 的时钟,速度我可以确定并且可以生成时间戳。但是,我找不到在后台 运行 这个时钟而不阻塞控制台的方法。我以为我可以使用 asyncio,但它没有像我预期的那样工作。这是代码:

import asyncio
import os
import math
simtime = 0
year = 2020
month = 10

try:
    TIMELAPSE = int(os.environ["TIMELAPSE"])
except KeyError:
    TIMELAPSE = 1


async def clock():
    global simtime
    while True:
        await asyncio.sleep(1)
        simtime += 1*TIMELAPSE


def timestamp():
    day = 1 + math.floor(simtime/86400)
    remaining = simtime % 86400
    hours = math.floor(remaining/3600)
    remaining = remaining % 3600
    minutes = math.floor(remaining/60)
    seconds = remaining % 60
    return f"{year}-{month}-{day}::{hours}:{minutes}:{seconds}"


loop = asyncio.get_event_loop()
loop.run_until_complete(clock())
loop.run_forever()

我以为时间会在后台进行,我可以使用 timestamp() 函数获取当前时间。

但是,当我这样做时 import clock,它会阻止脚本

我认为这是一个两部分的问题,首先是关于如何跟踪游戏中时光倒流,其次是关于如何使用非阻塞后台任务和 asyncio。

首先,您似乎只是每秒添加 simtime += 1*TIMELAPSE。在脚本开始时在变量中设置系统时间可能更简洁,然后当你想检查当前 simtime 时,你可以再次检查系统时间并减去起始系统时间,然后将结果乘以你的 TIMELAPSE .这应该等同于此脚本中使用 simtime 进行的操作,但要简单得多。

这个问题的第二部分,处理asyncio和non-blocking,我觉得你应该用asyncio.run_in_executor执行后台任务,然后你可以用run_until_complete执行您的前台任务如下。请注意,我在这里从时钟函数中删除了异步协程,并仅将 time.sleep 用于后台任务,因为执行程序不需要它作为该同步部分的协程。您可以 fiddle 使用时钟中的睡眠时间来验证它不会阻塞异步 some_other_task 协程。

import asyncio
import os
import math
import time
simtime = 0
year = 2020
month = 10

try:
    TIMELAPSE = int(os.environ["TIMELAPSE"])
except KeyError:
    TIMELAPSE = 1


def clock():
    global simtime
    while True:
        time.sleep(1)
        simtime += 1*TIMELAPSE
        print('Clock task simtime {}'.format(simtime))


def timestamp():
    day = 1 + math.floor(simtime/86400)
    remaining = simtime % 86400
    hours = math.floor(remaining/3600)
    remaining = remaining % 3600
    minutes = math.floor(remaining/60)
    seconds = remaining % 60
    return f"{year}-{month}-{day}::{hours}:{minutes}:{seconds}"


async def some_other_task():
    while True:
        print('Some other task using simtime {}'.format(simtime))
        await asyncio.sleep(1)

loop = asyncio.get_event_loop()
# run in background - None defaults to current loop executor
loop.run_in_executor(None, clock)
# run in foreground
loop.run_until_complete(some_other_task())
loop.run_forever()