为什么`time.sleep()`在超过100000000后会引发`IOError`?

3
我正在使用64位Mac OS X机器上的Python 2.7.10。为什么`time.sleep()`在100000000以后会引发一个`IOError`?
在下面的例子中,`time.sleep(100000000)`可以正常工作,但是`time.sleep(100000001)`会引发`IOError`。
$ python
Python 2.7.10 (default, Oct  6 2017, 22:29:07) 
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.31)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import time
>>> time.sleep(100000000)
^CTraceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyboardInterrupt
>>>
>>>
>>> time.sleep(100000001)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IOError: [Errno 22] Invalid argument

1
什么样的程序需要睡眠超过3年呢? - Julien
这不是生产代码。我只是好奇。 - Srikanth
我的猜测是,由于这些数字必须在运行时存储在某个有限大小的内存槽中,因此必须有一个上限。他们选择了一亿,这似乎对于任何实际情况都足够了。 - Julien
1个回答

4
这种行为是特定于 macOS,而不是 Python。Python使用select()函数来实现sleep,如果你尝试在 macOS 上运行超过1e8秒的select超时,则 Perl 会表现出相同的行为:
# perl -E 'select $x, $x, $x, 100000001; say $!'
Invalid argument

itimerfix函数位于XNU内核中,可能是此行为的罪魁祸首:

/*
 * Check that a proposed value to load into the .it_value or
 * .it_interval part of an interval timer is acceptable.
 */
int
itimerfix(
    struct timeval *tv)
{

    if (tv->tv_sec < 0 || tv->tv_sec > 100000000 ||
        tv->tv_usec < 0 || tv->tv_usec >= 1000000)
        return (EINVAL);
    return (0);
}

我是这个回复的忠实粉丝,干得好! - ayanami

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接