2012-11-08 63 views

Trả lời

61

Hãy thử như sau:

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 

Bạn cũng có thể muốn thêm một giấc ngủ ngắn ở đây nên vòng lặp này không hogging CPU (ví dụ time.sleep(1) ở đầu hoặc cuối của cơ thể loop).

+1

Cảm ơn bạn làm việc này :) – Adilicious

+0

tôi sử dụng 'timeit.default_timer', mà luôn luôn là đồng hồ chính xác nhất cho nền tảng này. Cụ thể, 'time.time' chỉ có độ chi tiết 1/60 s trên Windows, điều này có thể không đủ nếu bạn có thời gian chờ rất ngắn. Trên Python 3, cũng có 'time.monotonic',' time.perf_counter' và 'time.process_time', có thể tốt hơn (tôi chưa xử lý nhiều). – jpkotta

+3

Có quá nhiều điều kiện để xử lý trong giải pháp này. Điều này sẽ được tối ưu hóa và 'while True' được thay thế bằng' while time.time()

3
import time 

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

while True: 
    delta = time.time() - start 
    if delta >= abort_after: 
    break 
25

Hãy thử module này: 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 

Trân

+26

Knock knock - Ai đó? - Con bò bị gián đoạn - Con bò bị gián đoạn - ** MOOOOO **! –

+0

hahahah =) Và mọi thứ đều dừng lại! = P – andrefsp

+2

Giải pháp này phải là câu trả lời được chấp nhận theo ý kiến ​​của tôi. Nó thực hiện tốt hơn nhiều, tức là. nhiều mã hơn thực hiện bên trong vòng lặp trong một khoảng thời gian nhất định. – domoarrigato

22

Bạn không cần phải sử dụng while True: vòng lặp trong trường hợp này. Có một cách đơn giản hơn nhiều để sử dụng điều kiện thời gian trực tiếp:

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 
+0

Tại sao bạn không đề cập đến nhu cầu có thể xảy ra để ngăn CPU bị tải xuống bởi chức năng này bằng cách sử dụng chế độ ngủ? Mã này có thể hoạt động, nhưng nó sẽ không cần thiết sử dụng tài nguyên hệ thống. – Anthony

+0

Anthony, bạn có thể giải thích tại sao nó "không cần thiết sử dụng tài nguyên hệ thống?" Tôi thực sự tò mò và một chút bối rối; không ai khác ở trên time.sleep được sử dụng này(). Tại sao phải đặt kiểm tra logic trong tài nguyên hệ thống hog trong khi đó? –

+0

Điểm tốt về việc đặt kiểm tra thời gian chờ trong điều kiện vòng lặp while. Đối với nhận xét về 'time.sleep()', mã không hoạt động nên sẽ đi vòng qua vòng nhanh nhất có thể. Bằng cách thêm một 'time.sleep()' ngắn, CPU có thể không hoạt động thay vì chạy hết công suất trong khi không làm việc. – Baldrickk

2
câu trả lời

Petr Krampl là tốt nhất theo ý kiến ​​của tôi, nhưng nhu cầu nhiều hơn để được nói về bản chất của các vòng lặp và làm thế nào để tối ưu hóa việc sử dụng các hệ thống . Người mới bắt đầu xảy ra khi chuỗi này có thể bị nhầm lẫn hơn bởi các lỗi logic và thuật toán trong câu hỏi và câu trả lời hiện có.

Đầu tiên, chúng ta hãy nhìn vào những gì mã của bạn không như bạn ban đầu đã viết nó:

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

Nếu bạn nói while True trong một bối cảnh vòng lặp, thường ý định của bạn là ở trong vòng lặp mãi mãi. Nếu đó không phải là ý định của bạn, bạn nên xem xét các tùy chọn khác cho cấu trúc của vòng lặp. Petr Krampl cho bạn thấy một cách hoàn toàn hợp lý để xử lý vấn đề này rõ ràng hơn với người khác có thể đọc mã của bạn. Ngoài ra, nó sẽ rõ ràng hơn với bạn vài tháng sau đó nếu bạn cần phải truy cập lại mã của bạn để thêm hoặc sửa chữa một cái gì đó. Mã được viết tốt là một phần của tài liệu của bạn. Thường có nhiều cách để làm mọi thứ, nhưng điều đó không làm cho tất cả các cách đều hợp lệ trong mọi ngữ cảnh. while true là một ví dụ điển hình về điều này, đặc biệt trong ngữ cảnh này.

Tiếp theo, chúng tôi sẽ xem xét lỗi thuật toán trong mã ban đầu của bạn. Điều đầu tiên bạn làm trong vòng lặp là gán 0 đến test. Điều tiếp theo bạn cần làm là kiểm tra xem giá trị của test là 5, điều này sẽ không bao giờ xảy ra trừ khi bạn có nhiều chủ đề sửa đổi cùng một vị trí bộ nhớ. Luồng không nằm trong phạm vi của cuộc thảo luận này, nhưng đáng lưu ý rằng mã có thể hoạt động về mặt kỹ thuật, nhưng ngay cả với nhiều luồng sẽ bị thiếu, ví dụ: semaphores. Dù sao, bạn sẽ ngồi trong vòng lặp này mãi mãi bất kể thực tế là sentinel đang buộc một vòng lặp vô hạn.

Tuyên bố test = test - 1 là vô ích bất kể nó làm gì vì biến được đặt lại ở đầu vòng lặp tiếp theo của vòng lặp. Ngay cả khi bạn thay đổi nó thành test = 5, vòng lặp sẽ vẫn vô hạn vì giá trị được đặt lại mỗi lần. Nếu bạn di chuyển câu lệnh khởi tạo bên ngoài vòng lặp, thì ít nhất nó sẽ có cơ hội thoát ra. Những gì bạn có thể đã dự định là một cái gì đó như thế này:

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

Thứ tự của các câu lệnh trong vòng lặp phụ thuộc vào logic của chương trình của bạn.Nó sẽ làm việc theo một trong hai thứ, mặc dù, đó là điểm chính.

Vấn đề tiếp theo là lỗi logic có khả năng và có thể xảy ra bắt đầu từ 0, liên tục trừ đi 1, sau đó so sánh với số dương. Có, có những trường hợp điều này có thể thực sự là những gì bạn dự định làm miễn là bạn hiểu được các tác động, nhưng điều này rất có thể không phải là những gì bạn dự định. Phiên bản mới hơn của python sẽ không quấn quanh khi bạn đạt đến 'đáy' của phạm vi của một số nguyên như C và các ngôn ngữ khác. Nó sẽ cho phép bạn tiếp tục trừ 1 cho đến khi bạn đã lấp đầy bộ nhớ sẵn có trên hệ thống của mình hoặc ít nhất là những gì được phân bổ cho quá trình của bạn. Nhìn vào kịch bản sau đây và kết quả:

test = 0 

while True: 
    test -= 1 

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

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

trong đó sản xuất này:

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

Giá trị của test sẽ không bao giờ là 5, vì vậy vòng lặp này sẽ không bao giờ thoát.

Để thêm vào câu trả lời Petr Krampl của, đây là một phiên bản có lẽ gần gũi hơn với những gì bạn thực sự có ý định ngoài việc thoát khỏi vòng lặp sau một thời gian nhất định:

import time 

test = 0 
timeout = 300 # [seconds] 

timeout_start = time.time() 

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

Nó vẫn sẽ không phá vỡ dựa trên giá trị của test, nhưng đây là một vòng lặp hoàn toàn hợp lệ với điều kiện ban đầu hợp lý. Kiểm tra ranh giới tiếp theo có thể giúp bạn tránh việc thực hiện vòng lặp rất dài không có lý do, ví dụ: kiểm tra xem giá trị của phép thử có nhỏ hơn 5 khi nhập vòng lặp hay không, điều này sẽ ngay lập tức phá vỡ vòng lặp.


Một điều khác cần được đề cập là không có câu trả lời nào khác được giải quyết. Đôi khi bạn lặp lại như thế này, bạn có thể không muốn tiêu thụ CPU cho toàn bộ thời gian quy định. Ví dụ: giả sử bạn đang kiểm tra giá trị của thứ gì đó thay đổi mỗi giây. Nếu bạn không giới thiệu một số loại chậm trễ, bạn sẽ sử dụng mọi chu kỳ CPU có sẵn được phân bổ cho quá trình của bạn. Đó là tốt nếu nó là cần thiết, nhưng thiết kế tốt sẽ cho phép rất nhiều chương trình để chạy song song trên hệ thống của bạn mà không cần quá tải các nguồn lực sẵn có. Một câu lệnh ngủ đơn giản sẽ giải phóng phần lớn các chu kỳ CPU được phân bổ cho quá trình của bạn để các chương trình khác có thể làm việc.

Ví dụ sau không hữu ích lắm, nhưng nó thể hiện khái niệm. Giả sử bạn muốn in thứ gì đó mỗi giây. Một cách để làm điều đó sẽ là như thế này:

import time 

tCurrent = time.time() 

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

Kết quả sẽ là:

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

Và việc sử dụng quá trình CPU sẽ trông như thế này:

enter image description here

Đó là một số lượng lớn việc sử dụng CPU để làm cơ bản không có công việc.Mã này rất đẹp với phần còn lại của hệ thống:

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() 

Kết quả là như nhau:

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

và sử dụng CPU là bằng cách nào, cách thấp hơn:

enter image description here

0

Tôi muốn chia sẻ tài khoản tôi đang sử dụng:

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 
.210

Sau đó, bạn sẽ nhận được:

[1, 'looks ok'] 
[2, 'looks ok'] 
[7, 'too long'] 
[4, 'looks ok'] 
[5, 'too long'] 
[6, 'too long'] 
[4, 'looks ok'] 
[3, 'looks ok'] 
Các vấn đề liên quan