Python/Perl:定时循环实现(也是微秒)?

2024-09-29 17:10:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我想使用Perl和/或Python实现以下JavaScript伪代码:

var c=0;
function timedCount()
{
  c=c+1;
  print("c=" + c);

  if (c<10)  {
    var t;
    t=window.setTimeout("timedCount()",100);
  }
}

// main:
timedCount();
print("after timedCount()");

var i=0;
for (i=0; i<5; i++) {
  print("i=" + i);
  wait(500); //wait 500 ms
}

现在,这是一个非常不幸的选择作为基础的例子-但我只是想不出任何其他语言来提供它:)基本上,有一个“主循环”和一个辅助“循环”(timedCount),两者的计数率不同:main有500毫秒的周期(通过wait实现),timedCount,周期100毫秒(通过setInterval实现)。然而,JavaScript本质上是单线程的,而不是多线程的——因此,没有真正的sleep/wait/pause或类似的东西(参见JavaScript Sleep Function - ozzu.com),这就是为什么上面的代码是伪代码;)

但是,通过将主要部分移到另一个setInterval函数,我们可以得到一个代码版本,该版本可以粘贴并运行在类似JavaScript Shell 1.4的浏览器外壳中,而不是在EnvJS/Rhino这样的终端shell中):

^{pr2}$

。。。其结果如下:

i=1
c=1
after timedCount()
c=2
c=3
c=4
c=5
c=6
i=2
c=7
c=8
c=9
c=10
i=3
i=4
i=5

。。。也就是说,主计数和辅助计数是“交错的”/“线程的”/“分散的”,如预期的那样,大约每五个辅助计数就有一个主计数。在

现在的主要问题是,在Perl和Python中,推荐的方法是什么?在

  • 另外,Python或Perl是否提供了一些工具,以跨平台的方式以微秒级的时间分辨率实现上述功能?在

非常感谢您的回答,
干杯!在


Tags: 代码版本ifmainvarfunctionjavascriptwindow
3条回答

对于Perl,对于默认功能,How do I sleep for a millisecond in Perl?中声明:

  • sleep的分辨率为秒
  • select接受浮点,小数部分解释为毫秒

为了获得更高的分辨率,可以使用Time::HiRes模块,例如usleep()。在

如果使用默认的Perl功能,实现这种“线程化”计数的唯一方法似乎是“fork”脚本,让每个“fork”充当“thread”并进行自己的计数;我在Perl- How to call an event after a time delay - Perl上看到了这种方法,下面是一个修改后的版本,用于反映操作:

#!/usr/bin/env perl

use strict;
my $pid;

my $c=0;
my $i=0;

sub mainCount()
{
  print "mainCount\n";
  while ($i < 5) {
    $i = $i + 1;
    print("i=" . $i . "\n");
    select(undef, undef, undef, 0.5); # sleep 500 ms
  }
};

sub timedCount()
{
  print "timedCount\n";
  while ($c < 10) {
    $c = $c + 1;
    print("c=" . $c . "\n");
    select(undef, undef, undef, 0.1); # sleep 100 ms
  }
};


# main:
die "cant fork $!\n" unless defined($pid=fork());

if($pid) {
  mainCount();
} else {
  timedCount();
}

使用标准库^{}的简单python实现:

from threading import Timer

def timed_count(n=0):
    n += 1
    print 'c=%d' % n
    if n < 10:
        Timer(.1, timed_count, args=[n]).start()

def main_count(n=0):
    n += 1
    print 'i=%d' % n
    if n < 5:
        Timer(.5, main_count, args=[n]).start()

main_count()
timed_count()
print 'after timed_count()'

或者,使用类似twisted(在this answer)或{a4}(还有很多其他库)这样的异步库不会出错。在

我认为在Python中实现这一点的最简单和最一般的方法是使用Twisted(一个基于事件的网络引擎)来实现这一点。在

from twisted.internet import reactor
from twisted.internet import task

c, i = 0, 0
def timedCount():
    global c
    c += 1
    print 'c =', c

def mainCount():
    global i
    i += 1
    print 'i =', i

c_loop = task.LoopingCall(timedCount)
i_loop = task.LoopingCall(mainCount)
c_loop.start(0.1)
i_loop.start(0.5)
reactor.run()

Twisted有一个高效和稳定的事件循环实现,称为reactor。这使得它是单线程的,基本上与上面示例中的Javascript非常相似。我之所以用它来做像你上面的周期性任务,是因为它提供了一些工具,让你可以轻松地添加任意多个复杂的周期。在

它还提供more tools for scheduling task calls您可能会觉得有趣。在

相关问题 更多 >

    热门问题