【问题标题】:"WindowsError: Access is denied" on calling Process.terminate调用 Process.terminate 时出现“WindowsError:访问被拒绝”
【发布时间】:2013-06-12 22:49:27
【问题描述】:

我使用multiprocessing 模块对代码块强制执行超时。似乎对于特定大小的输入,会引发以下错误:

WindowsError: [Error 5] Access is denied

我可以使用以下代码复制此错误。请注意,代码以“467,912,040”结尾,但不是以“517,912,040”结尾。

import multiprocessing, Queue

def wrapper(queue, lst):
    lst.append(1)
    queue.put(lst)
    queue.close()

def timeout(timeout, lst):
    q = multiprocessing.Queue(1)
    proc = multiprocessing.Process(target=wrapper, args=(q, lst))
    proc.start()
    try:
        result = q.get(True, timeout)
    except Queue.Empty:
        return None
    finally:
        proc.terminate()
    return result

if __name__ == "__main__":
    # lst = [0]*417912040 # this works fine
    # lst = [0]*467912040 # this works fine
    lst = [0] * 517912040 # this does not
    print "List length:",len(lst)
    timeout(60*30, lst)

输出(包括错误):

List length: 517912040

Traceback (most recent call last):
  File ".\multiprocessing_error.py", line 29, in <module>
    print "List length:",len(lst)
  File ".\multiprocessing_error.py", line 21, in timeout
    proc.terminate()
  File "C:\Python27\lib\multiprocessing\process.py", line 137, in terminate
    self._popen.terminate()
  File "C:\Python27\lib\multiprocessing\forking.py", line 306, in terminate
    _subprocess.TerminateProcess(int(self._handle), TERMINATE)
WindowsError: [Error 5] Access is denied

是否允许我终止特定大小的进程?

我在 Windows 7(64 位)上使用 Python 2.7。

【问题讨论】:

  • 我不认为你激怒了 python……但它是一个你想要传输的大列表,当子进程处于奇怪状态时你可能超时(甚至可能还没有开始)。在我的系统上,仅仅腌制你的清单就花了 70 秒。您可以在终止失败时打印句柄并查看该进程是否存在。也许你可以睡一会再试一次。
  • 看起来问题与len(lst) 调用有关,这可能是因为queue 已损坏。在terminate() documentation 中突出显示了关于这可能发生的警告。

标签: python multiprocessing windowserror


【解决方案1】:

虽然我仍然不确定问题的确切原因,但我有一些额外的观察和解决方法。

解决方法。

在 finally 子句中添加 try-except 块。

finally:
    try:
        proc.terminate()
    except WindowsError:
        pass

这似乎也是在here on GitHub 发布的相关 (?) 问题中找到的解决方案(您可能需要向下滚动一点)。

观察。

  1. 此错误取决于传递给进程/队列的对象的大小,但与进程本身的执行无关。在 OP 中,Process 在超时到期之前完成。
  2. proc.is_alive 在执行 proc.terminate() 之前和之后返回 True(然后抛出 WindowsError)。一两秒后,proc.is_alive() 返回False,第二次调用proc.terminate() 成功。
  3. finally 块中强制主线程休眠time.sleep(1) 也可以防止抛出WindowsError。谢谢@tdelaney 在 OP 中的评论。
  4. 我的最佳猜测是proc 正在释放内存(?,或类似的东西),同时被操作系统杀死(已完成执行),而对proc.terminate() 的调用试图再次杀死它。

【讨论】:

    猜你喜欢
    • 2013-09-03
    • 2011-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-02
    • 2016-10-16
    • 1970-01-01
    相关资源
    最近更新 更多