関数呼び出しのタイムアウト


300

私はPythonで関数を呼び出していますが、これが停止してスクリプトを再起動するように強制する可能性があることがわかっています。

5秒以上かかる場合、スクリプトがそれをキャンセルして他のことを行うように、関数を呼び出す方法または何をラップするかを教えてください。

回答:


227

UNIXで実行している場合は、シグナルパッケージを使用できます。

In [1]: import signal

# Register an handler for the timeout
In [2]: def handler(signum, frame):
   ...:     print("Forever is over!")
   ...:     raise Exception("end of time")
   ...: 

# This function *may* run for an indetermined time...
In [3]: def loop_forever():
   ...:     import time
   ...:     while 1:
   ...:         print("sec")
   ...:         time.sleep(1)
   ...:         
   ...:         

# Register the signal function handler
In [4]: signal.signal(signal.SIGALRM, handler)
Out[4]: 0

# Define a timeout for your function
In [5]: signal.alarm(10)
Out[5]: 0

In [6]: try:
   ...:     loop_forever()
   ...: except Exception, exc: 
   ...:     print(exc)
   ....: 
sec
sec
sec
sec
sec
sec
sec
sec
Forever is over!
end of time

# Cancel the timer if the function returned before timeout
# (ok, mine won't but yours maybe will :)
In [7]: signal.alarm(0)
Out[7]: 0

呼び出しの10秒後、alarm.alarm(10)ハンドラーが呼び出されます。これにより、通常のPythonコードからインターセプトできる例外が発生します。

このモジュールはスレッドでうまく機能しません(しかし、だれがそうするのですか?)

タイムアウトが発生すると例外が発生するため、たとえば次のような関数のように、関数内でキャッチおよび無視される可能性があることに注意しください

def loop_forever():
    while 1:
        print('sec')
        try:
            time.sleep(10)
        except:
            continue

5
Python 2.5.4を使用しています。そのようなエラーがあります:トレースバック(最後の最新の呼び出し):ファイル "aa.py"、85行目、funcにsignal.signal(signal.SIGALRM、handler)AttributeError: 'module' object has no attribute 'SIGALRM'
flypen

11
@flypen signal.alarmとその関連SIGALRMはWindowsプラットフォームでは利用できないためです。
ダブルAA

2
多くのプロセスがあり、それぞれが呼び出す場合signal.signal---それらはすべて正しく動作しますか?signal.signal呼び出しごとに「並行」呼び出しをキャンセルしませんか?
ブラウニアン

1
これをC拡張で使用したい場合の警告:C関数が制御をPythonインタープリターに戻すまで、Pythonシグナルハンドラーは呼び出されません。この使用例については、ATOzTOAの回答を使用してください:stackoverflow.com/a/14924210/1286628
wkschwartz

13
スレッドについての警告の2番目です。signal.alarmはメインスレッドでのみ機能します。私はこれをDjangoビューで使用しようとしました-メインスレッドのみについての冗長ですぐに失敗します。
JL Peyret、2015

154

multiprocessing.Process正確にそれを行うために使用できます。

コード

import multiprocessing
import time

# bar
def bar():
    for i in range(100):
        print "Tick"
        time.sleep(1)

if __name__ == '__main__':
    # Start bar as a process
    p = multiprocessing.Process(target=bar)
    p.start()

    # Wait for 10 seconds or until process finishes
    p.join(10)

    # If thread is still active
    if p.is_alive():
        print "running... let's kill it..."

        # Terminate
        p.terminate()
        p.join()

36
ターゲットメソッドの戻り値を取得するにはどうすればよいですか?
bad_keypoints 2015

4
呼び出された関数がI / Oブロックでスタックしている場合、これは機能しないようです。
sudo

4
@bad_keypointsこの回答を参照してください:stackoverflow.com/a/10415215/1384471基本的に、回答を入れるリストを渡します。
Peter

1
次に@sudoを削除しjoin()ます。これにより、x個の同時サブプロセスが作業を完了するまで、またはで定義されjoin(10)た量だけ実行されます。join(10)を使用して10個のプロセスのブロックI / Oがある場合、それらがすべてのプロセスが開始されるのを最大10個待つように設定しました。この例のようにデーモンフラグを使用します。stackoverflow.com/a/27420072/2480481。もちろん、uはフラグdaemon=Truemultiprocessing.Process()関数に直接渡すことができます。
m3nda 2017年

2
@ATOzTOAこのソリューションの問題は、少なくとも私の目的では、子供が踏み台を自分で掃除することができない可能性があることです。終了機能の文書からterminate() ... Note that exit handlers and finally clauses, etc., will not be executed. Note that descendant processes of the process will not be terminated – they will simply become orphaned.
abalcerek

78

5秒以上かかる場合にスクリプトがそれをキャンセルするように、関数を呼び出す方法またはラップする方法を教えてください。

私はこの質問/問題をデコレータとで解決する要点を投稿しましたthreading.Timer。ここに内訳があります。

互換性のためのインポートとセットアップ

Python 2および3でテストされています。Unix/ LinuxおよびWindowsでも動作するはずです。

まずは輸入。これらは、Pythonのバージョンに関係なく、コードの一貫性を維持しようとします。

from __future__ import print_function
import sys
import threading
from time import sleep
try:
    import thread
except ImportError:
    import _thread as thread

バージョンに依存しないコードを使用します。

try:
    range, _print = xrange, print
    def print(*args, **kwargs): 
        flush = kwargs.pop('flush', False)
        _print(*args, **kwargs)
        if flush:
            kwargs.get('file', sys.stdout).flush()            
except NameError:
    pass

これで、標準ライブラリから機能がインポートされました。

exit_after デコレータ

次にmain()、子スレッドからを終了する関数が必要です。

def quit_function(fn_name):
    # print to stderr, unbuffered in Python 2.
    print('{0} took too long'.format(fn_name), file=sys.stderr)
    sys.stderr.flush() # Python 3 stderr is likely buffered.
    thread.interrupt_main() # raises KeyboardInterrupt

そしてここにデコレータ自体があります:

def exit_after(s):
    '''
    use as decorator to exit process if 
    function takes longer than s seconds
    '''
    def outer(fn):
        def inner(*args, **kwargs):
            timer = threading.Timer(s, quit_function, args=[fn.__name__])
            timer.start()
            try:
                result = fn(*args, **kwargs)
            finally:
                timer.cancel()
            return result
        return inner
    return outer

使用法

そして、5秒後に終了することについてのあなたの質問に直接答える使用法があります!:

@exit_after(5)
def countdown(n):
    print('countdown started', flush=True)
    for i in range(n, -1, -1):
        print(i, end=', ', flush=True)
        sleep(1)
    print('countdown finished')

デモ:

>>> countdown(3)
countdown started
3, 2, 1, 0, countdown finished
>>> countdown(10)
countdown started
10, 9, 8, 7, 6, countdown took too long
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 11, in inner
  File "<stdin>", line 6, in countdown
KeyboardInterrupt

2番目の関数呼び出しは終了せず、代わりにプロセスがトレースバックで終了します。

KeyboardInterrupt 常にスリープ状態のスレッドを停止するわけではありません

Windows上のPython 2では、スリープはキーボード割り込みによって常に割り込みされるわけではないことに注意してください。例:

@exit_after(1)
def sleep10():
    sleep(10)
    print('slept 10 seconds')

>>> sleep10()
sleep10 took too long         # Note that it hangs here about 9 more seconds
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 11, in inner
  File "<stdin>", line 3, in sleep10
KeyboardInterrupt

またPyErr_CheckSignals()、 明示的にをチェックしない限り、拡張機能で実行されているコードを中断することはありません。。Cython、Python、KeyboardInterruptが無視されるのをて

いずれにしても、スレッドを1秒以上スリープ状態にすることは避けます。これはプロセッサ時間の時代です。

5秒以上かかる場合、スクリプトがそれキャンセルして他のことを行うように、関数を呼び出す方法または何をラップするかを教えてください

それをキャッチして他のことを行うには、KeyboardInterruptをキャッチできます。

>>> try:
...     countdown(10)
... except KeyboardInterrupt:
...     print('do something else')
... 
countdown started
10, 9, 8, 7, 6, countdown took too long
do something else

私はまだあなたの投稿全体を読んでいませんでしたが、私は疑問に思いました:フラッシュが0の場合はどうなりますか?その下のifステートメントではFalseと解釈されますよね?
Koenraad van Duin

2
を呼び出す必要があるのはなぜですかthread.interrupt_main()、なぜ直接例外を発生させることができないのですか?
Anirban Nag 'tintinmj'

multiprocessing.connection.Clientこれでラップすることについて何か考えはありますか?-解決しようとすると:stackoverflow.com/questions/57817955/...
第二次世界大戦

51

純粋な関数である別の提案があり(スレッド化の提案と同じAPIを使用)、正常に機能しているようです(このスレッドの提案に基づく)

def timeout(func, args=(), kwargs={}, timeout_duration=1, default=None):
    import signal

    class TimeoutError(Exception):
        pass

    def handler(signum, frame):
        raise TimeoutError()

    # set the timeout handler
    signal.signal(signal.SIGALRM, handler) 
    signal.alarm(timeout_duration)
    try:
        result = func(*args, **kwargs)
    except TimeoutError as exc:
        result = default
    finally:
        signal.alarm(0)

    return result

3
元のシグナルハンドラも復元する必要があります。stackoverflow.com/questions/492519/…を
Martin Konecny 2013年

9
もう1つ注意:Unixシグナルメソッドは、メインスレッドで適用する場合にのみ機能します。サブスレッドで適用すると例外がスローされ、機能しません。
Martin Konecny 2013年

12
これはLinuxでのみ機能するため、最適なソリューションではありません。
最大

17
Max、trueではない-POSIX準拠のUNIXで動作します。あなたのコメントはもっと正確なはずだと思います。Windowsでは機能しません。
Chris Johnson

6
kwargsを空の辞書に設定しないでください。一般的なPythonの落とし穴は、関数のデフォルト引数が変更可能であることです。そのため、その辞書はへのすべての呼び出しで共有されtimeoutます。デフォルトをに設定しNone、関数の最初の行にを追加することをお勧めしkwargs = kwargs or {}ます。タプルは変更できないため、Argsは問題ありません。
scottmrogowski

32

ユニットテストでタイムアウトコールを検索しているときに、このスレッドに遭遇しました。私は回答やサードパーティのパッケージに簡単なものを見つけられなかったので、以下のデコレータを記述して、コードに直接ドロップできます。

import multiprocessing.pool
import functools

def timeout(max_timeout):
    """Timeout decorator, parameter in seconds."""
    def timeout_decorator(item):
        """Wrap the original function."""
        @functools.wraps(item)
        def func_wrapper(*args, **kwargs):
            """Closure for function."""
            pool = multiprocessing.pool.ThreadPool(processes=1)
            async_result = pool.apply_async(item, args, kwargs)
            # raises a TimeoutError if execution exceeds max_timeout
            return async_result.get(max_timeout)
        return func_wrapper
    return timeout_decorator

次に、テストや好きな関数をタイムアウトするのはこれと同じくらい簡単です:

@timeout(5.0)  # if execution takes longer than 5 seconds, raise a TimeoutError
def test_base_regression(self):
    ...

14
これはタイムアウトに達した後に機能を終了しないので注意してください!
Sylvain

Windowsでは、これにより完全に新しいプロセスが生成されることに注意してください-依存関係のセットアップに長い時間がかかる場合、タイムアウトまでに時間がかかります。
アーロンホール

1
はい、これには多少の調整が必要です。スレッドは永久に残ります。
sudo 2017年

2
これが最善の方法である場合はIDKですが、Exceptionfunc_wrapper内でtry / catch を実行pool.close()し、catchの後に実行することで、その後も常にスレッドが必ず終了するようにすることができます。その後、投げTimeoutErrorたり、好きなものを何でもできます。私のために働くようです。
sudo 2017年

2
これは便利ですが、何度も実行すると、が表示されますRuntimeError: can't start new thread。それを無視した場合でも機能しますか、これを回避するために他に何かできることはありますか?前もって感謝します!
Benjie 2017

20

stopitPyPIに存在するパッケージは、よくタイムアウトを処理しているようです。

私は@stopit.threading_timeoutableデコレータが好きです。timeout装飾された関数にパラメーターをです。期待どおりに機能し、関数を停止します。

pypiで確認してください:https ://pypi.python.org/pypi/stopit


1
とても便利でスレッドセーフです!ありがとう、プラスワン!これは私がこれまでに見つけた最良の選択肢であり、受け入れられた答えよりも優れています!!
Yahya、

ライブラリによると、一部の機能はWindowsでは機能しません。
Stefan Simik

16

提案はたくさんありますが、concurrent.futuresを使用する方法はありません。これは、これを処理する最も読みやすい方法だと思います。

from concurrent.futures import ProcessPoolExecutor

# Warning: this does not terminate function if timeout
def timeout_five(fnc, *args, **kwargs):
    with ProcessPoolExecutor() as p:
        f = p.submit(fnc, *args, **kwargs)
        return f.result(timeout=5)

読み取りと保守が非常に簡単です。

プールを作成し、単一のプロセスを送信してから、最大5秒待ってから、必要に応じてキャッチして処理できるTimeoutErrorを発生させます。

Python 3.2以降にネイティブで、2.7(pipインストール先物)にバックポートされています。

スレッドとプロセスの切り替えはProcessPoolExecutorThreadPoolExecutorです。

タイムアウト時にプロセスを終了したい場合は、Pebbleを調べることをお勧めします。


2
「警告:タイムアウトしても機能が終了しない」とはどういう意味ですか?
スコットスタッフォード2017

5
@ScottStaffordプロセス/スレッドは、TimeoutErrorが発生したからといって終了するわけではありません。そのため、プロセスまたはスレッドは最後まで実行を試み、タイムアウト時に自動的に制御を戻すことはありません。
ブライアン

これにより、その時点で中間的な結果を保存できますか?たとえば、タイムアウトを5に設定した再帰関数があり、その間に部分的な結果がある場合、タイムアウトで部分的な結果を返す関数をどのように記述すればよいですか?
SumNeuron 2018年

私はこれを正確に使用していますが、1000個のタスクがあり、それぞれがタイムアウトの5秒前に許可されています。私の問題は、タイムアウトが個々のタスクではなくタスクの合計にのみ適用されるため、コアが終了しないタスクで詰まることです。concurrent.futuresは、このafaikに対するソリューションを提供しません。
バスティ

12

使いやすく信頼性の高いPyPiプロジェクトのタイムアウトデコレータhttps://pypi.org/project/timeout-decorator/

インストール

pip install timeout-decorator

使用法

import time
import timeout_decorator

@timeout_decorator.timeout(5)
def mytest():
    print "Start"
    for i in range(1,10):
        time.sleep(1)
        print "%d seconds have passed" % i

if __name__ == '__main__':
    mytest()

2
明確な解決策に感謝します。しかし、このライブラリがどのように機能するか、特にマルチスレッドを扱う場合はだれでも説明できますか?個人的には、未知のメカニズムを使用してスレッドやシグナルを処理することを恐れています。
wsysuper 2018年

@wsysuper the libには2つの操作モードがあります。新しいスレッドを開くか、新しいサブプロセス(スレッドセーフであると想定されます)
Gil

これは私にとって非常にうまくいきました!
フロリアン・ハイグル

6

私はwrapt_timeout_decoratorの作成者です

ここで紹介するほとんどのソリューションは一目でLinuxの下で素晴らしく機能します-fork()とsignals()があるためですが、Windowsでは状況が少し異なります。Linuxのサブスレッドに関しては、シグナルを使用することはできません。

Windowsでプロセスを生成するには、プロセスを選択可能にする必要があります。装飾された関数やクラスメソッドの多くは選択できません。

したがって、dillやマルチプロセス(ピクルやマルチプロセシングではない)などのより優れたピッカーを使用する必要があります。そのため、ProcessPoolExecutorを使用できません(または機能が制限されている場合のみ)。

タイムアウト自体について-タイムアウトの意味を定義する必要があります-Windowsでは、プロセスを生成するのにかなりの(そして決定できない)時間を要するためです。これは、短いタイムアウトでは注意が必要です。プロセスの起動には約0.5秒かかります(簡単に!!!)。0.2秒のタイムアウトを指定するとどうなりますか?関数は0.5 + 0.2秒後にタイムアウトする必要がありますか(メソッドを0.2秒実行します)?または、呼び出されたプロセスは0.2秒後にタイムアウトする必要がありますか(その場合、装飾された関数は常にタイムアウトになります。

また、ネストされたデコレータは厄介な場合があり、サブスレッドでシグナルを使用することはできません。本当に普遍的なクロスプラットフォームのデコレーターを作成したい場合は、これらすべてを考慮に入れる(そしてテストする)必要があります。

その他の問題は、例外を呼び出し元に返しているだけでなく、ロギングの問題です(装飾された関数で使用されている場合-別のプロセスでのファイルへのロギングはサポートされていません)。

私はすべてのエッジケースをカバーしようとしました。パッケージwrapt_timeout_decoratorを調べるか、少なくともそこで使用されているユニットテストに触発された独自のソリューションをテストしてください。

@Alexis Eggermont-残念ながら、コメントするのに十分なポイントがありません-多分誰かがあなたに通知することができます-私はあなたのインポートの問題を解決したと思います。


3

timeout-decorator Windowsシステムでは動作しません。Windowsはサポートしていません signalてた。

Windowsシステムでtimeout-decoratorを使用すると、次のようになります。

AttributeError: module 'signal' has no attribute 'SIGALRM'

一部は使用することを提案しました use_signals=Falseが、うまくいきませんでした。

著者@bitranoxは次のパッケージを作成しました:

pip install https://github.com/bitranox/wrapt-timeout-decorator/archive/master.zip

コードサンプル:

import time
from wrapt_timeout_decorator import *

@timeout(5)
def mytest(message):
    print(message)
    for i in range(1,10):
        time.sleep(1)
        print('{} seconds have passed'.format(i))

def main():
    mytest('starting')


if __name__ == '__main__':
    main()

次の例外があります。

TimeoutError: Function mytest timed out after 5 seconds

これは非常に良い解決策のように聞こえます。奇妙なことに、このラインfrom wrapt_timeout_decorator import * は私の他の輸入品のいくつかを殺しているようです。たとえば、を取得しましたがModuleNotFoundError: No module named 'google.appengine'、wrapt_timeout_decoratorをインポートしない場合、このエラーは発生しません
Alexis Eggermont

@AlexisEggermont appengineでこれを使用しようとしていました...このエラーが引き続き発生するかどうか、私は非常に興味がありますか?
PascalVKooten

2

信号も同じように使えます。以下の例が参考になると思います。スレッドに比べて非常に簡単です。

import signal

def timeout(signum, frame):
    raise myException

#this is an infinite loop, never ending under normal circumstances
def main():
    print 'Starting Main ',
    while 1:
        print 'in main ',

#SIGALRM is only usable on a unix platform
signal.signal(signal.SIGALRM, timeout)

#change 5 to however many seconds you need
signal.alarm(5)

try:
    main()
except myException:
    print "whoops"

1
特定の例外を選択して、それだけをキャッチする方が良いでしょう。裸try: ... except: ...は常に悪い考えです。
2013

私はあなたがハイバートすることに同意します。
AR

私は理由を理解していますが、sysadmin / integratorとして私は同意しません-Pythonコードはエラー処理を無視することで悪名高く、期待されている1つのことを処理するだけでは高品質のソフトウェアには不十分です。計画している5つのことと、他の一般的な戦略を処理できます。「Traceback、None」は戦略ではなく、侮辱です。
フロリアン・ハイグル

2
#!/usr/bin/python2
import sys, subprocess, threading
proc = subprocess.Popen(sys.argv[2:])
timer = threading.Timer(float(sys.argv[1]), proc.terminate)
timer.start()
proc.wait()
timer.cancel()
exit(proc.returncode)

7
このコードは質問に答えるかもしれませんが、問題を解決する方法および/または理由に関する追加のコンテキストを提供すると、回答の長期的な価値が向上します
Dan Cornilescu

1

入れ子にする必要があった time.sleep(スレッドベースのアプローチではできない)によってブロックされない時限割り込み(SIGALARMではできない)が。私はここからコードをコピーして軽く変更しました:http : //code.activestate.com/recipes/577600-queue-for-managing-multiple-sigalrm-alarms-concurr/

コード自体:

#!/usr/bin/python

# lightly modified version of http://code.activestate.com/recipes/577600-queue-for-managing-multiple-sigalrm-alarms-concurr/


"""alarm.py: Permits multiple SIGALRM events to be queued.

Uses a `heapq` to store the objects to be called when an alarm signal is
raised, so that the next alarm is always at the top of the heap.
"""

import heapq
import signal
from time import time

__version__ = '$Revision: 2539 $'.split()[1]

alarmlist = []

__new_alarm = lambda t, f, a, k: (t + time(), f, a, k)
__next_alarm = lambda: int(round(alarmlist[0][0] - time())) if alarmlist else None
__set_alarm = lambda: signal.alarm(max(__next_alarm(), 1))


class TimeoutError(Exception):
    def __init__(self, message, id_=None):
        self.message = message
        self.id_ = id_


class Timeout:
    ''' id_ allows for nested timeouts. '''
    def __init__(self, id_=None, seconds=1, error_message='Timeout'):
        self.seconds = seconds
        self.error_message = error_message
        self.id_ = id_
    def handle_timeout(self):
        raise TimeoutError(self.error_message, self.id_)
    def __enter__(self):
        self.this_alarm = alarm(self.seconds, self.handle_timeout)
    def __exit__(self, type, value, traceback):
        try:
            cancel(self.this_alarm) 
        except ValueError:
            pass


def __clear_alarm():
    """Clear an existing alarm.

    If the alarm signal was set to a callable other than our own, queue the
    previous alarm settings.
    """
    oldsec = signal.alarm(0)
    oldfunc = signal.signal(signal.SIGALRM, __alarm_handler)
    if oldsec > 0 and oldfunc != __alarm_handler:
        heapq.heappush(alarmlist, (__new_alarm(oldsec, oldfunc, [], {})))


def __alarm_handler(*zargs):
    """Handle an alarm by calling any due heap entries and resetting the alarm.

    Note that multiple heap entries might get called, especially if calling an
    entry takes a lot of time.
    """
    try:
        nextt = __next_alarm()
        while nextt is not None and nextt <= 0:
            (tm, func, args, keys) = heapq.heappop(alarmlist)
            func(*args, **keys)
            nextt = __next_alarm()
    finally:
        if alarmlist: __set_alarm()


def alarm(sec, func, *args, **keys):
    """Set an alarm.

    When the alarm is raised in `sec` seconds, the handler will call `func`,
    passing `args` and `keys`. Return the heap entry (which is just a big
    tuple), so that it can be cancelled by calling `cancel()`.
    """
    __clear_alarm()
    try:
        newalarm = __new_alarm(sec, func, args, keys)
        heapq.heappush(alarmlist, newalarm)
        return newalarm
    finally:
        __set_alarm()


def cancel(alarm):
    """Cancel an alarm by passing the heap entry returned by `alarm()`.

    It is an error to try to cancel an alarm which has already occurred.
    """
    __clear_alarm()
    try:
        alarmlist.remove(alarm)
        heapq.heapify(alarmlist)
    finally:
        if alarmlist: __set_alarm()

そして使用例:

import alarm
from time import sleep

try:
    with alarm.Timeout(id_='a', seconds=5):
        try:
            with alarm.Timeout(id_='b', seconds=2):
                sleep(3)
        except alarm.TimeoutError as e:
            print 'raised', e.id_
        sleep(30)
except alarm.TimeoutError as e:
    print 'raised', e.id_
else:
    print 'nope.'

これはシグナルも使用するため、スレッドから呼び出された場合は機能しません。
garg10may 2018年

0

以下は、与えられたスレッドベースのソリューションのわずかな改善です。

以下のコードは例外をサポートしています

def runFunctionCatchExceptions(func, *args, **kwargs):
    try:
        result = func(*args, **kwargs)
    except Exception, message:
        return ["exception", message]

    return ["RESULT", result]


def runFunctionWithTimeout(func, args=(), kwargs={}, timeout_duration=10, default=None):
    import threading
    class InterruptableThread(threading.Thread):
        def __init__(self):
            threading.Thread.__init__(self)
            self.result = default
        def run(self):
            self.result = runFunctionCatchExceptions(func, *args, **kwargs)
    it = InterruptableThread()
    it.start()
    it.join(timeout_duration)
    if it.isAlive():
        return default

    if it.result[0] == "exception":
        raise it.result[1]

    return it.result[1]

5秒のタイムアウトでそれを呼び出す:

result = timeout(remote_calculate, (myarg,), timeout_duration=5)

1
これにより、元のトレースバックを非表示にする新しい例外が発生します。以下の私のバージョンを参照してください...
Meitham

1
これは、runFunctionCatchExceptions()GILを取得する特定のPython関数内で呼び出されるかのように、安全ではありません。たとえば、関数内で呼び出された場合、次のコードは決して、または非常に長い間戻りませんeval(2**9999999999**9999999999)stackoverflow.com/questions/22138190/…を
Mikko Ohtamaa 2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.