আমি এটির মতো ব্যতিক্রমী সতর্কতাটি কীভাবে ধরব (কেবল পরীক্ষার জন্য নয়)?


173

আমি যে প্রকল্পটি করছি তার জন্য আমাকে পাইথনে একটি ল্যাঞ্জরেঞ্জ বহুপদী তৈরি করতে হবে। নিউটনের বিভক্ত পার্থক্য শৈলীর বিপরীতে স্পষ্টভাবে লুপ ব্যবহার এড়াতে আমি ব্যারিসেন্ট্রিক স্টাইল করছি। আমার সমস্যাটি হ'ল আমার শূন্য দ্বারা একটি বিভাগ ধরা দরকার, তবে পাইথন (বা সম্ভবত ছদ্মবেশী) এটিকে একটি সাধারণ ব্যতিক্রমের পরিবর্তে কেবল একটি সতর্কবার্তা করে তোলে।

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

import numpy as np
import matplotlib.pyplot as plt
import warnings

class Lagrange:
    def __init__(self, xPts, yPts):
        self.xPts = np.array(xPts)
        self.yPts = np.array(yPts)
        self.degree = len(xPts)-1 
        self.weights = np.array([np.product([x_j - x_i for x_j in xPts if x_j != x_i]) for x_i in xPts])

    def __call__(self, x):
        warnings.filterwarnings("error")
        try:
            bigNumerator = np.product(x - self.xPts)
            numerators = np.array([bigNumerator/(x - x_j) for x_j in self.xPts])
            return sum(numerators/self.weights*self.yPts) 
        except Exception, e: # Catch division by 0. Only possible in 'numerators' array
            return yPts[np.where(xPts == x)[0][0]]

L = Lagrange([-1,0,1],[1,0,1]) # Creates quadratic poly L(x) = x^2

L(1) # This should catch an error, then return 1. 

এই কোডটি কার্যকর করা হলে, আমি যে আউটপুট পাই তা হ'ল:

Warning: divide by zero encountered in int_scalars

আমি সেই সতর্কতাটি ধরতে চাই এটি তালিকা বোধের ভিতরে হওয়া উচিত inside


2
তুমি কি নিশ্চিত এটা নিশ্চিত Warning: ...? np.array([1])/0আমি RuntimeWarning: ...আউটপুট হিসাবে পেতে মত জিনিস চেষ্টা করে ।
বাকুরিউ

1
@ ম্যাডফিজিসিস্ট একটি সদৃশ নয়; পাইপথনের শীর্ষে নুমপির নিজস্ব অভ্যন্তরীণ সতর্কতা আর্কিটেকচার রয়েছে, যা বিশেষভাবে নিয়ন্ত্রণ করা যেতে পারে (বাকুরুর উত্তর দেখুন)।
অঙ্কুর

@gerrit। আমি সংশোধন করে দাঁড়িয়েছি এবং একটি নতুন জিনিস শিখেছি। ব্যাজ সংগ্রহের উন্মাদনা ট্রিগার করতে এড়াতে আমি আমার আসল মন্তব্যটি মুছে ফেলেছি।
ম্যাড পদার্থবিজ্ঞানী

আপনি যে অন্য পদ্ধতির ব্যবহার করতে পারেন তা হ'ল বিভাজনের আগে ডিনোমিনেটর 0 হয় কিনা তা যাচাই করে নিন, যা নম্পার সতর্কতা সিস্টেমের সাথে ফিডলিংয়ের ওভারহেড এড়িয়ে চলে। (যদিও এর অর্থ সম্ভবত হ'ল ডিনোমিনেটরগুলির কোনও শূন্য কিনা আপনার ঝরঝরে পরীক্ষার ঝরঝরে পরিষ্কার তালিকা অনুধাবনকে প্রসারিত করতে হবে))
অলিভার

উত্তর:


197

দেখে মনে হচ্ছে আপনার কনফিগারেশনটি এর জন্য printবিকল্পটি ব্যবহার করছে numpy.seterr:

>>> import numpy as np
>>> np.array([1])/0   #'warn' mode
__main__:1: RuntimeWarning: divide by zero encountered in divide
array([0])
>>> np.seterr(all='print')
{'over': 'warn', 'divide': 'warn', 'invalid': 'warn', 'under': 'ignore'}
>>> np.array([1])/0   #'print' mode
Warning: divide by zero encountered in divide
array([0])

এর অর্থ এই যে সতর্কবার্তা আপনি দেখতে হয় না একটি বাস্তব সতর্কবার্তা, কিন্তু এটা শুধু কিছু অক্ষর মুদ্রিত এর stdout(জন্য ডকুমেন্টেশান দেখুন seterr)। আপনি যদি এটি ধরতে চান তবে আপনি এটি করতে পারেন:

  1. numpy.seterr(all='raise')সরাসরি ব্যতিক্রম উত্থাপন করবে যা ব্যবহার করুন । এটি তবে সমস্ত ক্রিয়াকলাপের আচরণকে পরিবর্তন করে, সুতরাং এটি আচরণে একটি দুর্দান্ত পরিবর্তন big
  2. ব্যবহার করুন numpy.seterr(all='warn'), যা প্রকৃত সতর্কতায় মুদ্রিত সতর্কবার্তাকে রূপান্তরিত করবে এবং আচরণের এই পরিবর্তনটি স্থানীয়করণের জন্য আপনি উপরের সমাধানটি ব্যবহার করতে সক্ষম হবেন।

একবার আপনার কাছে আসলে একটি সতর্কতা হয়ে গেলে, warningsসতর্কতাগুলি কীভাবে আচরণ করা উচিত তা নিয়ন্ত্রণ করতে আপনি মডিউলটি ব্যবহার করতে পারেন :

>>> import warnings
>>> 
>>> warnings.filterwarnings('error')
>>> 
>>> try:
...     warnings.warn(Warning())
... except Warning:
...     print 'Warning was raised as an exception!'
... 
Warning was raised as an exception!

সাবধানে ডকুমেন্টেশন পড়ুন filterwarningsকারণ এটি আপনাকে কেবল যে সতর্কতাটি চায় তা ফিল্টার করতে দেয় এবং অন্যান্য বিকল্প রয়েছে has আমি catch_warningsকোন প্রসঙ্গে ম্যানেজার যা স্বয়ংক্রিয়ভাবে মূল filterwarningsফাংশনটি পুনরায় সেট করে তা দেখার বিষয়ে আমি বিবেচনা করব :

>>> import warnings
>>> with warnings.catch_warnings():
...     warnings.filterwarnings('error')
...     try:
...         warnings.warn(Warning())
...     except Warning: print 'Raised!'
... 
Raised!
>>> try:
...     warnings.warn(Warning())
... except Warning: print 'Not raised!'
... 
__main__:2: Warning: 

আমি মনে করি এটি একটি শুরু। তবে এটি আসলে আমার সমস্যার সমাধান করে না। যদি আমি চেষ্টা ব্লকে আমার কোডে সতর্কতা.ওয়ার্ন (সতর্কতা ()) যুক্ত করি তবে এটি সতর্কতাটি ধরবে। কিছু কারণে এটি শূন্য সতর্কতা দ্বারা বিভাজন ধরা দেয় না। এখানে হুশিয়ারী বার্তাটি হ'ল: সতর্কতা: শূণ্য দ্বারা বিভক্ত হওয়া ইনটস্কেলারে
জন কে।

@JohnK। আপনার নিজের প্রশ্নটি সম্পাদনা করা উচিত এবং সঠিক আউটপুট যুক্ত করা উচিত, অন্যথায় আমরা কী ভুল তা বলতে পারি না। এটি সম্ভব হতে পারে যে নম্পি এই সতর্কতা শ্রেণীর কোথাও সংজ্ঞায়িত করেছে এবং আপনাকে কোন উপ-প্যাকেজটি এটি ধরতে সক্ষম হবে তা আবিষ্কার করতে হবে। কিছু মনে করবেন না, আমি আবিষ্কার করেছি যে আপনার ব্যবহার করা উচিত RuntimeWarning। উত্তর আপডেট করেছেন।
বাকুরিউ

তুমি কি নিশ্চিত? আমি আমার কোডটি রানটাইম ওয়ার্নিং ব্যতীত ব্যবহার করতে পরিবর্তন করেছি:। এটি এখনও কাজ করছে না = /
জন কে।

@JohnK। ডকুমেন্টেশনে এটি বলা হয়েছে যে একটি RuntimeWarningউত্থাপিত হয়েছে। সমস্যাটি হতে পারে যে আপনার নামী কনফিগারেশনটি printবিকল্পটি ব্যবহার করছে , যা কেবলমাত্র সতর্কতাটি মুদ্রণ করে তবে এটি warningsমডিউল দ্বারা পরিচালিত কোনও সত্যিকারের সতর্কতা নয় ... যদি এটি হয় তবে আপনি ব্যবহার করার চেষ্টা করতে পারেন numpy.seterr(all='warn')এবং আবার চেষ্টা করতে পারেন ।
বাকুরিউ

3
আমার সংস্করণে numpy, আপনি ব্যবহার করতে পারবেন না numpy.seterr(all='error'), হওয়া errorদরকার raise
স্পষ্টত

41

@ বাকুরির উত্তরে কিছুটা যুক্ত করতে:

যদি আপনি ইতিমধ্যে জানেন যে সতর্কতাটি কোথায় ঘটেছিল সম্ভবত তবে numpy.errstateপ্রাসঙ্গিক ব্যবস্থাপক ব্যবহার করা প্রায়শই পরিষ্কার er তার পরিবর্তে numpy.seterrএকই ধরণের সমস্ত পরবর্তী সতর্কবাণীগুলি আপনার কোডের মধ্যে যেখানেই আসে তা নির্বিশেষে একই রকম আচরণ করে:

import numpy as np

a = np.r_[1.]
with np.errstate(divide='raise'):
    try:
        a / 0   # this gets caught and handled as an exception
    except FloatingPointError:
        print('oh no!')
a / 0           # this prints a RuntimeWarning as usual

সম্পাদনা:

আমার আসল উদাহরণটিতে আমার ছিল a = np.r_[0], তবে স্পষ্টতই স্তম্ভীর আচরণে এমন পরিবর্তন এসেছে যে সংখ্যাটি অল-জিরো হয় এমন ক্ষেত্রে বিভাগ দ্বারা শূন্যকে আলাদাভাবে পরিচালনা করা হয়। উদাহরণস্বরূপ, অলস 1.16.4 এ:

all_zeros = np.array([0., 0.])
not_all_zeros = np.array([1., 0.])

with np.errstate(divide='raise'):
    not_all_zeros / 0.  # Raises FloatingPointError

with np.errstate(divide='raise'):
    all_zeros / 0.  # No exception raised

with np.errstate(invalid='raise'):
    all_zeros / 0.  # Raises FloatingPointError

সম্পর্কিত সতর্কতা বার্তা এছাড়াও পৃথক: 1. / 0.হিসাবে লগ ইন হয় RuntimeWarning: divide by zero encountered in true_divide, যেখানে 0. / 0.লগ ইন RuntimeWarning: invalid value encountered in true_divide। এই পরিবর্তনটি কেন করা হয়েছিল তা আমি নিশ্চিত নই, তবে আমার সন্দেহ হয় যে এটির ফলাফলটি 0. / 0.একটি সংখ্যার হিসাবে উপস্থাপনযোগ্য নয় (নিম্পি এই ক্ষেত্রে একটি এনএএন প্রদান করে) 1. / 0.এবং -1. / 0.+ ইনফ এবং যথাক্রমে ফিরে আসে আইইই 754 মান অনুযায়ী।

আপনি যদি উভয় ধরণের ত্রুটি ধরতে চান তবে আপনি সর্বদা পাস করতে পারেন np.errstate(divide='raise', invalid='raise')বা all='raise'আপনি যদি কোনও ধরণের ফ্লোটিং পয়েন্ট ত্রুটির ব্যতিক্রম বাড়াতে চান ।


উল্লেখযোগ্যভাবে এটি উত্থাপন FloatingPointError, না ZeroDivisionError
ছত্রাক

এই কাজ করে না Python 3.6.3সঙ্গে numpy==1.16.3। আপনি দয়া করে এটি আপডেট করতে পারেন?
anilbey

1
@ অ্যানিলবি স্পষ্টতই নমপির আচরণে পরিবর্তন এসেছে যার অর্থ শূন্যটি বিভাগ দ্বারা বাই এখন শূন্যের উপর নির্ভর করে এখন আলাদাভাবে পরিচালিত হবে।
ali_m

27

উপরে @ বাকুরির উত্তরটি বিস্তারিতভাবে বর্ণনা করার জন্য, আমি খুঁজে পেয়েছি যে এটি আমাকে কোনও রানটাইম সতর্কতা ধরতে সক্ষম করে আমি কীভাবে ত্রুটি সতর্কতাটি ধরব, সতর্কবার্তাটি সুন্দরভাবে ছাপিয়ে দেব:

import warnings

with warnings.catch_warnings():
    warnings.filterwarnings('error')
    try:
        answer = 1 / 0
    except Warning as e:
        print('error found:', e)

আপনি সম্ভবত ত্রুটিগুলি ধরার ক্ষেত্রে কতটা বড় ছাতা ফেলতে চান তার উপর নির্ভর করে আপনি সম্ভবত সতর্কবাণীগুলি দেখুন atch


3
উত্তর =
1/0

8

সতর্কতাগুলি.ফিল্টার সতর্কতাগুলি সরান এবং যুক্ত করুন:

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