87

達成したいことが達成されない場合、5分後にwhileループを停止するにはどうすればよいですか。

while true:
    test = 0
    if test == 5:
        break
    test = test - 1

このコードは私を無限ループに陥らせます。

4

9 に答える 9

143

次のことを試してください。

import time
timeout = time.time() + 60*5   # 5 minutes from now
while True:
    test = 0
    if test == 5 or time.time() > timeout:
        break
    test = test - 1

ここに短いスリープを追加して、このループが CPU を占有しないようにすることもできます (たとえばtime.sleep(1)、ループ本体の最初または最後で)。

于 2012-11-08T16:30:41.740 に答える
47

while True:この場合、ループを使用する必要はありません。時間条件を直接使用するもっと簡単な方法があります。

import time

# timeout variable can be omitted, if you use specific value in the while condition
timeout = 300   # [seconds]

timeout_start = time.time()

while time.time() < timeout_start + timeout:
    test = 0
    if test == 5:
        break
    test -= 1
于 2014-06-19T11:41:58.560 に答える
40

このモジュールを試してください: http://pypi.python.org/pypi/interruptingcow/

from interruptingcow import timeout
try:
    with timeout(60*5, exception=RuntimeError):
        while True:
            test = 0
            if test == 5:
                break
            test = test - 1
except RuntimeError:
    pass
于 2012-11-08T16:32:47.503 に答える
21

私の意見では、Petr Krampl の回答が最良ですが、ループの性質とシステムの使用を最適化する方法については、さらに説明する必要があります。このスレッドに出くわした初心者は、質問と既存の回答の論理的およびアルゴリズム的なエラーによってさらに混乱する可能性があります。

最初に、最初に書いたときのコードの動作を見てみましょう。

while True:
    test = 0
    if test == 5:
        break
    test = test - 1

ループ コンテキストで言うとwhile True、通常、意図はループに永遠にとどまることです。それが意図されていない場合は、ループの構造について他のオプションを検討する必要があります。Petr Krampl は、これを処理するための完全に合理的な方法を示しました。これは、あなたのコードを読む可能性のある他の誰かにとってより明確です。さらに、何かを追加または修正するためにコードを再検討する必要がある場合、数か月後にはより明確になります。よく書かれたコードはドキュメントの一部です。通常、物事を行うには複数の方法がありますが、すべての方法がすべてのコンテキストで等しく有効になるわけではありません。while true特にこの文脈では、これの良い例です。

次に、元のコードのアルゴリズム エラーを確認します。ループで最初に行うことは、 に 0 を代入することtestです。次に行うことは、 の値testが 5 であるかどうかを確認することです。これは、同じメモリ位置を変更する複数のスレッドがない限り、決して当てはまりません。スレッド化はこの議論の対象ではありませんが、コードは技術的には機能する可能性があることに注意してください。とにかく、センチネルが無限ループを強制しているという事実に関係なく、このループに永遠に座ります.

test = test - 1ループの次の反復の開始時に変数がリセットされるため、ステートメントが何を行うかに関係なく、ステートメントは役に立ちません。に変更してもtest = 5、毎回値がリセットされるため、ループは無限になります。初期化ステートメントをループの外に移動すると、少なくとも終了する可能性があります。あなたが意図したのは次のようなものでした:

test = 0
while True:
    test = test - 1
    if test == 5:
        break

ループ内のステートメントの順序は、プログラムのロジックによって異なります。ただし、どちらの順序でも機能します。これが主なポイントです。

次の問題は、0 から開始して継続的に 1 を減算し、正の数と比較するという論理エラーの可能性と可能性です。はい、意味を理解している限り、これが実際に意図したことである場合がありますが、これは意図したものではない可能性が最も高いです。python の新しいバージョンは、C や他のさまざまな言語のように、整数の範囲の「底」に達したときにラップアラウンドしません。システムで使用可能なメモリがいっぱいになるまで、または少なくともプロセスに割り当てられているものがいっぱいになるまで、1を減算し続けることができます。次のスクリプトと結果を見てください。

test = 0

while True:
    test  -= 1

    if test % 100 == 0:
        print "Test = %d" % test

    if test == 5:
        print "Test = 5"
        break

これはこれを生成します:

Test = -100
Test = -200
Test = -300
Test = -400
...
Test = -21559000
Test = -21559100
Test = -21559200
Test = -21559300
...

の値testが 5 になることはないため、このループは終了しません。

Petr Kramplの回答に追加するために、一定期間後にループを終了することに加えて、おそらく実際に意図したものに近いバージョンを次に示します。

import time

test = 0
timeout = 300   # [seconds]

timeout_start = time.time()

while time.time() < timeout_start + timeout:
    if test == 5:
        break
    test -= 1

の値に基づいて壊れることはありませんtestが、これは妥当な初期条件を持つ完全に有効なループです。さらに境界チェックを行うと、理由もなく非常に長いループが実行されるのを回避するのに役立ちます。たとえば、ループの開始時に test の値が 5 未満であるかどうかをチェックすると、すぐにループが中断されます。


もう1つ、他の回答が対処されていないことに言及する必要があります。このようにループすると、割り当てられた時間全体で CPU を消費したくない場合があります。たとえば、毎秒変化するものの値をチェックしているとします。なんらかの遅延を導入しないと、プロセスに割り当てられた利用可能なすべての CPU サイクルを使用することになります。必要な場合はそれで問題ありませんが、優れた設計により、使用可能なリソースに過度の負担をかけることなく、システム上で多くのプログラムを並行して実行できます。シンプルな sleep ステートメントは、プロセスに割り当てられた CPU サイクルの大部分を解放し、他のプログラムが作業できるようにします。

次の例はあまり役に立ちませんが、概念を示しています。毎秒何かを印刷したいとしましょう。それを行う1つの方法は次のようになります。

import time

tCurrent = time.time()

while True:
    if time.time() >= tCurrent + 1:
        print "Time = %d" % time.time()
        tCurrent = time.time()

出力は次のようになります。

Time = 1498226796
Time = 1498226797
Time = 1498226798
Time = 1498226799

プロセスの CPU 使用率は次のようになります。

ここに画像の説明を入力

これは、基本的に何の作業も行わないのに膨大な量の CPU 使用率です。このコードは、システムの残りの部分にはるかに適しています。

import time

tCurrent = time.time()

while True:
    time.sleep(0.25) # sleep for 250 milliseconds
    if time.time() >= tCurrent + 1:
        print "Time = %d" % time.time()
        tCurrent = time.time()

出力は同じです。

Time = 1498226796
Time = 1498226797
Time = 1498226798
Time = 1498226799

そしてCPU使用率はかなり低いです:

ここに画像の説明を入力

于 2017-06-23T14:12:48.700 に答える
6
import time

abort_after = 5 * 60
start = time.time()

while True:
  delta = time.time() - start
  if delta >= abort_after:
    break
于 2012-11-08T16:31:11.680 に答える
1

私が使用しているものを共有したい:

import time
# provide a waiting-time list:
lst = [1,2,7,4,5,6,4,3]
# set the timeout limit
timeLimit = 4

for i in lst:
    timeCheck = time.time()
    while True:
        time.sleep(i)
        if time.time() <= timeCheck + timeLimit:
            print ([i,'looks ok'])
            break
        else:
            print ([i,'too long'])
            break

次に、次のようになります。

[1, 'looks ok']
[2, 'looks ok']
[7, 'too long']
[4, 'looks ok']
[5, 'too long']
[6, 'too long']
[4, 'looks ok']
[3, 'looks ok']
于 2017-07-28T21:19:04.537 に答える