ব্যতিক্রমের পরে আবার চেষ্টা করবেন কীভাবে?


251

আমি একটি লুপ দিয়ে শুরু করেছি for i in range(0, 100)। সাধারণত এটি সঠিকভাবে চলে তবে কখনও কখনও নেটওয়ার্কের কারণে এটি ব্যর্থ হয়। বর্তমানে আমি এটি সেট করে রেখেছি যাতে ব্যর্থতার পরে, এটি continueব্যতীত বাদে (পরবর্তী নম্বরটিতে অবিরত থাকবে i)।

আমার পক্ষে কি একই নম্বরটি পুনরায় নিয়োগ করা iএবং লুপটির ব্যর্থ পুনরাবৃত্তিটি দিয়ে আবার চালানো সম্ভব?


1
আপনি range(100)প্রথম প্যারামিটার ছাড়াই ব্যবহার করতে পারেন । আপনি যদি পাইথন ২.x ব্যবহার করেন এমনকি আপনি এটি ব্যবহার করতে পারেন তবে এটি xrange(100)একটি পুনরুক্তি তৈরি করে এবং কম স্মৃতি ব্যবহার করে। (এটি কেবল 100 টি বস্তুর সাথে গুরুত্বপূর্ণ নয়))
জর্জি স্কলি


2
সেই থ্রেডে স্বেচ্ছাসেবক অভিযান পরিচালনা করার জন্য সমর্থন সহ সজ্জকার ব্যবহার করে একটি খুব মার্জিত সমাধান রয়েছে
zitroneneis

উত্তর:


378

while Trueলুপের জন্য আপনার ভিতরে একটি অভ্যন্তর করুন, আপনার tryকোডটি ভিতরে রেখে দিন এবং whileআপনার কোডটি সফল হলে সেই লুপটি থেকে বিরতি দিন ।

for i in range(0,100):
    while True:
        try:
            # do stuff
        except SomeSpecificException:
            continue
        break

30
@ ইগনাসিও, হাহ ? continueচেষ্টার whileলুপ, অবশ্যই, নাfor , তাই (!) iহয় না "পরবর্তী" কিছু - এটা ঠিক একই যেমন একটি পূর্ববর্তী (ব্যর্থ হয়েছে) একই পায়ে ছিল whileঅবশ্যই,।
অ্যালেক্স মার্টেলি

13
Xorsyst নোট হিসাবে, এটি সেখানে আবার চেষ্টা করার সীমা রাখার পরামর্শ দেওয়া হচ্ছে। অন্যথায় আপনি বেশ কিছু সময়ের জন্য লুপিং আটকে যেতে পারেন।
ব্র্যাড কোচ

2
এই একটি চমৎকার উদাহরণ medium.com/@echohack/...
টনি Melony

7
আমি অবশ্যই সত্যটি: লাইনটি ছেড়ে দেব, অন্যথায় বিরতি উইল বাইরের লুপকে ক্লান্তিতে অবিরত রাখবে।
জানুয়ারী

1
@ সংকল্প, আমার কাছে মনে হয়েছে যে উত্তরটি প্রশ্নের পাঠ্যের জন্য উপযুক্ত।
জিনাক

187

আমি পুনরায় প্রচেষ্টার সংখ্যা সীমাবদ্ধ করতে পছন্দ করি, যাতে নির্দিষ্ট আইটেমটিতে কোনও সমস্যা থাকলে আপনি অবশেষে পরেরটিটিতে চালিয়ে যান, এভাবে:

for i in range(100):
  for attempt in range(10):
    try:
      # do thing
    except:
      # perhaps reconnect, etc.
    else:
      break
  else:
    # we failed all the attempts - deal with the consequences.

3
@ g33kz0r পাইথনের অপর নির্মাণের জন্য লুপটি না ভাঙ্গলে অন্য ধারাটি কার্যকর করে। সুতরাং, এই ক্ষেত্রে, বিভাগটি কার্যকর করে যদি আমরা সমস্ত 10 টি প্রচেষ্টা চেষ্টা করি এবং সর্বদা একটি ব্যতিক্রম পাই।
xorsyst

7
এটি একটি দুর্দান্ত উত্তর! সত্যই আরও অনেকগুলি উপার্জনের দাবিদার। এটি পাইথনের সমস্ত সুবিধা পুরোপুরি ব্যবহার করে, বিশেষত এর কম জ্ঞাত else:ধারা for
পেপলুয়ান

2
চেষ্টা শেষে আপনার বিরতি দরকার নেই: অংশ? অতিরিক্ত বিরতির চেষ্টা সহ :, প্রক্রিয়াটি সফলভাবে শেষ হলে লুপটি ভেঙে যায়, যদি এটি সফলভাবে সম্পন্ন না হয় তবে এটি সরাসরি ব্যতিক্রম অংশে চলে যাবে। যে জানার জন্য? যদি আমি চেষ্টা শেষে একটি বিরতি না রাখি: এটি কেবল 100 বার জিনিসটি করে।
ত্রিস্তান

1
@Tristan - elseধারা tryএই "সফল হলে, তারপর বিরতি" যে আপনি খুঁজছেন না।
PaulMcG

1
আমি আবার চেষ্টা করার জন্য একটি লুপ পছন্দ করি। এই except
কোডটির একটি কুঁচকির শব্দটি হ'ল

69

পুনরায় চেষ্টা করা হচ্ছে প্যাকেজ ব্যর্থতা কোডটি একটি ব্লক পুনরায় চেষ্টা করতে একটা চমৎকার উপায়।

উদাহরণ স্বরূপ:

@retry(wait_random_min=1000, wait_random_max=2000)
def wait_random_1_to_2_s():
    print("Randomly wait 1 to 2 seconds between retries")

4
আরও সাধারণভাবে, পাইপির পুনরায় চেষ্টা সাজানোর
ক্যারেট

আপনি যেভাবে ব্যর্থ হয়েছেন প্রতিবার চেষ্টা করার সংখ্যাটি কীভাবে মুদ্রণ করতে পারবেন?
dim_user

8
যেহেতু আমি বুঝতে পেরেছি যে রক্ষণাবেক্ষণ করা হচ্ছে না, আরও সক্রিয় কাঁটাটি github.com/jd/tenacity এবং সম্ভবত github.com/litl/backoff ব্যবহার করা যেতে পারে।
আলেক্সি

22

এখানে অন্যদের অনুরূপ একটি সমাধান রয়েছে, তবে এটি নির্ধারিত সংখ্যায় সফল না হলে বা পুনরায় চেষ্টা করতে ব্যর্থ হবে।

tries = 3
for i in range(tries):
    try:
        do_the_thing()
    except KeyError as e:
        if i < tries - 1: # i is zero indexed
            continue
        else:
            raise
    break

উত্তম উত্তর, তবে পরিবর্তনশীল নামটি retriesবিভ্রান্তিকর। এটা অনেক বেশি হওয়া উচিত tries
লুকাস

সত্য @ লুকাস। সংশোধন করা হয়েছে।
TheHerk

খুব ভাল সমাধান আপনাকে ধন্যবাদ। প্রতিটি চেষ্টা মধ্যে একটি বিলম্ব যোগ করে এটি উন্নত করা যেতে পারে। API গুলি নিয়ে কাজ করার সময় খুব দরকারী।
স্যাম

14

লুপগুলি চলাকালীন u কুৎসিতগুলি ব্যবহার না করে আরও "কার্যকরী" পদ্ধতির:

def tryAgain(retries=0):
    if retries > 10: return
    try:
        # Do stuff
    except:
        retries+=1
        tryAgain(retries)

tryAgain()

13
আমি দুঃখিত, তবে এটি "কুরুচিপূর্ণ যখন লুপস" ভেরিয়েন্টগুলির চেয়ে অনেক খারাপ বলে মনে হচ্ছে; এবং আমি কার্যকরী প্রোগ্রামিংয়ের অনুরাগী ...
lvela

9
আপনাকে অবশ্যই গভীরভাবে পুনরাবৃত্তি না করার বিষয়টি নিশ্চিত করতে হবে - পাইথনে ডিফল্ট স্ট্যাকের আকার 1000
Cal Paterson

5
এটি যদি 'কার্যকরী' হতে চলেছে, তবে পুনরাবৃত্তিটি হওয়া উচিত:except: tryAgain(retries+1)
কামারানা

এটির সাথে সমস্যাটি হ'ল আমাদের ভেরিয়েবল হিসাবে চারপাশে ত্রুটিটি পাস করতে হবে।
লোজাওও

11

সুস্পষ্ট উপায় হ'ল সুস্পষ্টভাবে সেট করা i। উদাহরণ স্বরূপ:

i = 0
while i < 100:
    i += 1
    try:
        # do stuff

    except MyException:
        continue

37
সে সি বা সি ++? আমি বলতে পারি না।
জর্জি স্কলি

5
@ জর্গ এটি পাইথন, যেমনটি প্রশ্নের মধ্যে বলা হয়েছে। বা যেখানে কোনও কারণে আপনাকে ব্যঙ্গাত্মক করা হচ্ছে?
Jakob Borg

2
এটি ওপি যা বলেছিল তা করে না। আপনি i += 1ঠিক পরে রাখলে এটি হতে পারে # do stuff
fmalina

5
পাইথোনিক নয়। rangeএই ধরণের জিনিসগুলির জন্য ব্যবহার করা উচিত ।
রহস্যময়

2
আমি সম্মত, এটি অবশ্যই ব্যাপ্তি ব্যবহার করবে।
ব্যবহারকারী 2662833

5

একটি সময়সীমা সহ একটি জেনেরিক সমাধান:

import time

def onerror_retry(exception, callback, timeout=2, timedelta=.1):
    end_time = time.time() + timeout
    while True:
        try:
            yield callback()
            break
        except exception:
            if time.time() > end_time:
                raise
            elif timedelta > 0:
                time.sleep(timedelta)

ব্যবহার:

for retry in onerror_retry(SomeSpecificException, do_stuff):
    retry()

ত্রুটি পরীক্ষার জন্য পৃথক ফাংশন নির্দিষ্ট করা সম্ভব? এটি কলব্যাকের আউটপুট নেবে এবং ত্রুটি যাচাইয়ের কার্যক্রমে কোনও সিদ্ধান্ত নেওয়ার পরিবর্তে এটি কোনও সাধারণ ব্যবহার না করে ব্যর্থতা বা সাফল্য হবেexcept exception:
প্রতীক খাদলোয়া

এর পরিবর্তে try … exceptআপনি একটি ifবিবৃতি ব্যবহার করতে পারেন । তবে অজগরটি কম।
লরেন্ট LAPORTE

এই সমাধান কাজ করে না। trinket.io/python/caeead4f6b do_stuff দ্বারা নিক্ষিপ্ত ব্যতিক্রমটি জেনারেটরে বুদবুদ নয়। কেন হবে, যাইহোক? do_stuff কে লুপের শরীরে ডাকা হয়, যা নিজে থেকে বাইরের স্তরে থাকে, জেনারেটরে থাকে না।
ইসরান্দি

আপনার অধিকার, তবে ভিন্ন কারণে: callbackফাংশনটি কখনই ডাকা হয় না। আমি প্রথম বন্ধনী ভুলে গেছি, দ্বারা প্রতিস্থাপন callback()
লরেন্ট LAPORTE

5
for _ in range(5):
    try:
        # replace this with something that may fail
        raise ValueError("foo")

    # replace Exception with a more specific exception
    except Exception as e:
        err = e
        continue

    # no exception, continue remainder of code
    else:
        break

# did not break the for loop, therefore all attempts
# raised an exception
else:
    raise err

আমার সংস্করণ উপরের কয়েকটিটির মতোই, তবে একটি পৃথক whileলুপ ব্যবহার করে না এবং সমস্ত চেষ্টা ব্যর্থ হলে সর্বশেষ ব্যতিক্রমটি পুনরায় উত্থাপন করে। সুস্পষ্টভাবে err = Noneশীর্ষে সেট করা যেতে পারে , তবে কঠোরভাবে প্রয়োজনীয় নয় কারণ এটির মধ্যে elseযদি কোনও ত্রুটি ছিল এবং তাই errসেট করা থাকে তবে কেবলমাত্র চূড়ান্ত ব্লকটি কার্যকর করা উচিত ।


4

পাইথন ডেকোরেটর লাইব্রেরিতে অনুরূপ কিছু রয়েছে ।

দয়া করে মনে রাখবেন যে এটি ব্যতিক্রমগুলির জন্য পরীক্ষা করে না, তবে ফেরতের মান। সজ্জিত ফাংশনটি সত্য না হওয়া পর্যন্ত এটি পুনরায় চেষ্টা করে।

কিছুটা পরিবর্তিত সংস্করণটি কৌশলটি করা উচিত।


ব্যতিক্রমগুলির জন্য এটি কীভাবে সংশোধন করবেন তা এখানে রয়েছে সালটিক্রেন.com
অ্যান্টনি

4

পুনরাবৃত্তি ব্যবহার করে

for i in range(100):
    def do():
        try:
            ## Network related scripts
        except SpecificException as ex:
            do()
    do() ## invoke do() whenever required inside this loop

1
প্রস্থান শর্ত? বা এই 100 * অনন্ত চালায়?
ingyhere

3

সময় এবং একটি কাউন্টার ব্যবহার করে:

count = 1
while count <= 3:  # try 3 times
    try:
        # do_the_logic()
        break
    except SomeSpecificException as e:
        # If trying 3rd time and still error?? 
        # Just throw the error- we don't have anything to hide :)
        if count == 3:
            raise
        count += 1

3

আপনি পাইথন পুনরায় চেষ্টা প্যাকেজ ব্যবহার করতে পারেন। পুনরায় চেষ্টা করা হচ্ছে

পাইথনে লিখে দেওয়া হয়েছে কেবল কোনও বিষয়ে পুনরায় চেষ্টা করার কাজটি সহজ করার জন্য।


2

এর বিকল্পগুলি retrying: tenacityএবং backoff(2020 আপডেট)

পুনরায় চেষ্টা করা হচ্ছে গ্রন্থাগার পূর্বে যেতে উপায় ছিল, কিন্তু দুঃখিতভাবে এটি কিছু বাগ এবং যেহেতু 2016. অন্যান্য বিকল্প হবে বলে মনে হচ্ছে এটা কোন আপডেট পেয়েছেন backoff এবং তানতা । এটি লেখার সময়, তাত্পর্যটিতে আরও জিআইটিহাব তারা ছিল (২.৩ কে বনাম ১.২ কে) এবং সম্প্রতি আপডেট হয়েছিল, তাই আমি এটি ব্যবহার করা বেছে নিয়েছি। এখানে একটি উদাহরণ:

from functools import partial
import random # producing random errors for this example

from tenacity import retry, stop_after_delay, wait_fixed, retry_if_exception_type

# Custom error type for this example
class CommunicationError(Exception):
    pass

# Define shorthand decorator for the used settings.
retry_on_communication_error = partial(
    retry,
    stop=stop_after_delay(10),  # max. 10 seconds wait.
    wait=wait_fixed(0.4),  # wait 400ms 
    retry=retry_if_exception_type(CommunicationError),
)()


@retry_on_communication_error
def do_something_unreliable(i):
    if random.randint(1, 5) == 3:
        print('Run#', i, 'Error occured. Retrying.')
        raise CommunicationError()

উপরের কোডটি এরকম কিছু আউটপুট করে:

Run# 3 Error occured. Retrying.
Run# 5 Error occured. Retrying.
Run# 6 Error occured. Retrying.
Run# 6 Error occured. Retrying.
Run# 10 Error occured. Retrying.
.
.
.

এর জন্য আরও সেটিংস তাত্পর্য গিটহাব পৃষ্ঠায়tenacity.retry তালিকাভুক্ত করা হয়েছে ।


1

আপনি যদি নেস্টেড লুপগুলি ছাড়াই এবং breakসাফল্যের জন্য অনুরোধ না করে সমাধান চান তবে যে retriableকোনও পুনরাবৃত্তির জন্য দ্রুত মোড়ক বিকাশ করতে পারেন । নেটওয়ার্কিং সমস্যার একটি উদাহরণ এখানে আমি প্রায়শই চালাচ্ছি - সংরক্ষিত প্রমাণীকরণের মেয়াদ শেষ হয়ে যায়। এটির ব্যবহার এভাবে পড়বে:

client = get_client()
smart_loop = retriable(list_of_values):

for value in smart_loop:
    try:
        client.do_something_with(value)
    except ClientAuthExpired:
        client = get_client()
        smart_loop.retry()
        continue
    except NetworkTimeout:
        smart_loop.retry()
        continue

1

আমি আমার কোডগুলিতে নিম্নলিখিত ব্যবহার করি,

   for i in range(0, 10):
    try:
        #things I need to do
    except ValueError:
        print("Try #{} failed with ValueError: Sleeping for 2 secs before next try:".format(i))
        time.sleep(2)
        continue
    break


0

এখানে এই বিষয়ে আমার গ্রহণ। নিম্নলিখিত retryফাংশনটি নিম্নলিখিত বৈশিষ্ট্যগুলিকে সমর্থন করে:

  • আমন্ত্রিত ক্রিয়াকলাপটি সাফল্যের সাথে প্রত্যাবর্তন করে
  • চেষ্টার অবসান হলে অনুরোধ করা ফাংশনটির ব্যতিক্রম উত্থাপন
  • প্রচেষ্টার সংখ্যা সীমাবদ্ধ (সীমাহীন জন্য 0)
  • প্রচেষ্টার মধ্যে অপেক্ষা করুন (রৈখিক বা ঘৃণ্য)
  • ব্যতিক্রমটি কোনও নির্দিষ্ট ব্যতিক্রম প্রকারের উদাহরণ হলেই আবার চেষ্টা করুন।
  • প্রচেষ্টা ptionচ্ছিক লগিং
import time

def retry(func, ex_type=Exception, limit=0, wait_ms=100, wait_increase_ratio=2, logger=None):
    attempt = 1
    while True:
        try:
            return func()
        except Exception as ex:
            if not isinstance(ex, ex_type):
                raise ex
            if 0 < limit <= attempt:
                if logger:
                    logger.warning("no more attempts")
                raise ex

            if logger:
                logger.error("failed execution attempt #%d", attempt, exc_info=ex)

            attempt += 1
            if logger:
                logger.info("waiting %d ms before attempt #%d", wait_ms, attempt)
            time.sleep(wait_ms / 1000)
            wait_ms *= wait_increase_ratio

ব্যবহার:

def fail_randomly():
    y = random.randint(0, 10)
    if y < 10:
        y = 0
    return x / y


logger = logging.getLogger()
logger.setLevel(logging.INFO)
logger.addHandler(logging.StreamHandler(stream=sys.stdout))

logger.info("starting")
result = retry.retry(fail_randomly, ex_type=ZeroDivisionError, limit=20, logger=logger)
logger.info("result is: %s", result)

আরও তথ্যের জন্য আমার পোস্ট দেখুন ।


-2

এটি কীভাবে ঠিক করা যায় সে সম্পর্কে আমার ধারণাটি এখানে:

j = 19
def calc(y):
    global j
    try:
        j = j + 8 - y
        x = int(y/j)   # this will eventually raise DIV/0 when j=0
        print("i = ", str(y), " j = ", str(j), " x = ", str(x))
    except:
        j = j + 1   # when the exception happens, increment "j" and retry
        calc(y)
for i in range(50):
    calc(i)

7
এটি বেস বন্ধ উপায়।
ক্রিস জনসন

-2

আমি সম্প্রতি আমার অজগরটির সাথে এই সমস্যার সমাধানের জন্য কাজ করেছি এবং স্ট্যাকওভারফ্লো দর্শকদের সাথে ভাগ করে নিতে পেরে আমি খুশী দয়া করে যদি এটির প্রয়োজন হয় তবে প্রতিক্রিয়া জানান।

print("\nmonthly salary per day and year converter".title())
print('==' * 25)


def income_counter(day, salary, month):
    global result2, result, is_ready, result3
    result = salary / month
    result2 = result * day
    result3 = salary * 12
    is_ready = True
    return result, result2, result3, is_ready


i = 0
for i in range(5):
    try:
        month = int(input("\ntotal days of the current month: "))
        salary = int(input("total salary per month: "))
        day = int(input("Total Days to calculate> "))
        income_counter(day=day, salary=salary, month=month)
        if is_ready:
            print(f'Your Salary per one day is: {round(result)}')
            print(f'your income in {day} days will be: {round(result2)}')
            print(f'your total income in one year will be: {round(result3)}')
            break
        else:
            continue
    except ZeroDivisionError:
        is_ready = False
        i += 1
        print("a month does'nt have 0 days, please try again")
        print(f'total chances left: {5 - i}')
    except ValueError:
        is_ready = False
        i += 1
        print("Invalid value, please type a number")
        print(f'total chances left: {5 - i}')

-8

যখন চেষ্টা ক্লাউজ সফল হয় তখনই আপনার লুপের পরিবর্তনশীল বৃদ্ধি করুন

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.