2013-04-10 4 views
96

मुझे एक परियोजना के लिए पायथन में एक लैंगेंज बहुपद बनाना है। न्यूटन की विभाजित अंतर शैली के विपरीत एक स्पष्ट फॉर-लूप का उपयोग करने से बचने के लिए मैं एक बेरेंट्रिक शैली कर रहा हूं। मेरी समस्या यह है कि मुझे शून्य से एक विभाजन पकड़ने की आवश्यकता है, लेकिन पायथन (या शायद numpy) सिर्फ एक सामान्य अपवाद के बजाय चेतावनी देता है।मैं एक अपवाद चेतावनी कैसे पकड़ सकता हूं जैसे यह एक अपवाद है (न केवल परीक्षण के लिए)?

तो, मुझे यह जानने की जरूरत है कि इस चेतावनी को पकड़ना कैसा है जैसे कि यह एक अपवाद था। इस साइट पर मिले इस से संबंधित प्रश्नों का उत्तर मुझे जिस तरह से आवश्यक था, उसमें उत्तर नहीं दिया गया था।

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 

चेतावनी मैं पकड़ने के लिए चाहते हैं यही कारण है कि। यह सूची समझ के अंदर होना चाहिए।

+2

आप काफी यकीन है कि यह' चेतावनी है कर रहे हैं? 'Np.array ([1])/0' जैसी चीजों को आजमाकर मुझे आउटपुट के रूप में 'रनटाइम चेतावनी: ...' मिलता है। – Bakuriu

+0

@MadPhysicist डुप्लिकेट नहीं; न्यूमपी के पास पाइथन के शीर्ष पर अपनी आंतरिक चेतावनी वास्तुकला है, जिसे विशेष रूप से नियंत्रित किया जा सकता है (Bakuríu द्वारा जवाब देखें)। – gerrit

+0

@gerrit। मैं सही हो गया और एक नई बात सीखा। बैज संग्रह उन्माद ट्रिगर करने से बचने के लिए मैंने अपनी मूल टिप्पणी हटा दी। –

उत्तर

117

ऐसा नहीं है कि आपके विन्यास numpy.seterr के लिए print विकल्प का उपयोग कर रहा है लगता है:

>>> 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') का उपयोग करें जो सीधे अपवाद उठाएगा। हालांकि यह सभी परिचालनों के व्यवहार को बदलता है, इसलिए यह व्यवहार में एक बहुत बड़ा बदलाव है।
  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 के लिए प्रलेखन के बाद से यह आप केवल चेतावनी फिल्टर करने के लिए अनुमति देता है आप चाहते हैं और अन्य विकल्प हैं। जहां चेतावनी संभावना है

आप पहले से ही जानते हैं:

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

मुझे लगता है कि यह एक शुरुआत है। लेकिन यह वास्तव में मेरी समस्या को ठीक नहीं करता है। अगर मैं चेतावनी जोड़ता हूं। चेतावनी (चेतावनी())) मेरे कोड में कोशिश ब्लॉक में, यह चेतावनी पकड़ लेगा। किसी कारण से यह शून्य चेतावनी से विभाजन को पकड़ नहीं लेता है। यहां सटीक चेतावनी संदेश दिया गया है: चेतावनी: int_scalars –

+0

@JohnK में शून्य से विभाजित। आपको अपना प्रश्न संपादित करना चाहिए और सटीक आउटपुट जोड़ना चाहिए, अन्यथा हम यह नहीं बता सकते कि क्या गलत है। यह * संभव हो सकता है कि numpy कहीं भी इस चेतावनी वर्ग को परिभाषित करता है और आपको यह पता लगाना होगा कि किस उप-पैकेज को पकड़ने में सक्षम होना चाहिए। कोई बात नहीं, मैंने पाया कि आपको 'रनटाइमर्निंग' का उपयोग करना चाहिए। उत्तर अपडेट किया गया। – Bakuriu

+0

क्या आप निश्चित हैं? मैंने रनटाइम चेतावनी को छोड़कर उपयोग करने के लिए अपना कोड बदल दिया:। यह अभी भी काम नहीं कर रहा है =/ –

20

एक छोटे @ करने के लिए Bakuriu के जवाब जोड़ने के लिए: मैं भी catch_warnings को देखकर जो एक संदर्भ प्रबंधक जो स्वचालित रूप से मूल filterwarnings समारोह रीसेट करता है पर विचार कर रहे तो होने के लिये यह numpy.seterr जो एक ही प्रकार उसी के बाद के सभी चेतावनियों जहां वे अपने कोड के भीतर होने की परवाह किए बिना व्यवहार करता है की तुलना में numpy.errstate संदर्भ प्रबंधक का उपयोग करने के बजाय, अक्सर क्लीनर है:

import numpy as np 

a = np.r_[0] 
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 
+0

उल्लेखनीय रूप से यह 'फ़्लोटिंगपॉइंट एरर' उठाता है, न कि 'शून्य डीविजन एरर'। – gerrit

12

ऊपर @ Bakuriu के जवाब पर विस्तार से बता दें मैं पाया है कि इस मुझे कैसे मैं एक त्रुटि चेतावनी पकड़ होता है, अच्छी तरह से चेतावनी को प्रिंट करने के लिए इसी तरह से एक क्रम चेतावनी को पकड़ने के लिए सक्षम बनाता है:

import warnings 

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

आप संभवत: चेतावनियां.catch_warnings() प्लेसमेंट को रखने के साथ-साथ इस तरह के छेड़छाड़ की त्रुटियों के साथ आप जिस छाता को डालना चाहते हैं, इस पर निर्भर करता है।

1

warnings.filterwarnings निकालें और जोड़ें: ... `:

numpy.seterr(all='raise') 
संबंधित मुद्दे