2017-04-19 10 views
2

オブジェクトコードで警告が表示され、何か起こったことをユーザに警告しますが、コードを停止させません。以下は、私は私の実際のコードに遭遇しています、より複雑なシナリオに基づいて、単純なモックアップである:私の実際のコードでユーザに警告しようとしているものの後にPythonの警告が来る

from warnings import warn 
class myClass(object):   
    def __init__(self, numberArg): 

     if numberArg > 1000: 
      self._tmpTxt = "That's a really big number for this code." + \ 
          "Code may take a while to run..." 
      warn("\n%s %s" %(numberArg, self._tmpTxt)) 
      print("If this were real code:") 
      print("Actions code takes because this is a big number would happen here.") 

     print("If this were real code, it would be doing more stuff here ...") 

mc1 = myClass(1001) 

、私は__init__(self, numberArg)を実行するクラスをインスタンス化し、警告が最後の出力は、すべての後です警告に続く処理が行われます。なぜこれが起こるのですか?

さらに重要なことは、警告が最初に出力され、残りのコードが実行され、その出力が確実に出力されるようにする方法はありますか?

ここに示す例のように、望ましい結果は、起こる前に何が起こるかをユーザに警告し、その後ではなく、警告フォーマットの警告のように出力を出すことです。

注:この問題は、

+0

'warn'はコマンドラインから遅れていませんでした。メッセージがstderrに送られます。おそらく、あなたの環境がそれを見るのを遅らせます。 – tdelaney

+0

私はwarn()の振る舞いが好きです。問題のモジュール名、コード行番号、提案された警告メッセージのフォーマットをピンク色で出力し、ユーザーに何か間違っていることを警告します。問題を回避する方法はありますか?アイデアを歓迎します。 (ちょうど私のコードを良くしようとしています)。注意:遅延理論に関しては、この例のコードは瞬間的ですが、実際のコードでは計算に3分以上かかってしまい、警告が最後に表示されます。遅延の場合は、時間ベースではなく「すべてのコードが完了した後に遅延する」と思われます。 – TMWP

+1

フラッシングスタンダードはどうですか?それはとにかく助けてくれますか? – direprobs

答えて

2

@direprobsはコメントでこの質問への最も簡単な答えを提供するWindows 7の環境でiPython/JupyterでPython 2.7を使用して発生しました。 warn()への呼び出しの後、このコード行を追加してください。

sys.stderr.flush()

注:それはsysライブラリから来ているけどwarningsstderrに書き込み、すでにライブラリをインポートするので、あなたはimport文は必要ありません。

このコードをコピー・アンド・ペーストしすぐにそれを実行し、効果を確認するためのPython 2.7(Jupyterノートブック)にすることができます。

実験ワン(それを次のコードとの比較のために):

# Note how warnings in this sample are held until after code is run and then output at the end ... 

from warnings import warn 
from warnings import resetwarnings 

class myClass(object):   
    def __init__(self, numberArg): 

     if numberArg > 1000: 
      self._tmpTxt = "That's a really big number for this code." + \ 
          "Code may take a while to run..." 
      warn("\n%s %s" %(numberArg, self._tmpTxt), stacklevel=1, category=RuntimeWarning) 
                 # possible categories (some of them): 
                 # UserWarning, Warning, RunTimeWarning, ResourceWarning 
                 # stacklevel was a experiment w/ no visible effect 
                 # in this instance 

      resetwarnings()       # tried putting this before and after the warn() 
      print("If this were real code:") 
      print("Actions code takes because this is a big number would happen here.") 

     print("If this were real code, it would be doing more stuff here ...") 

mc1 = myClass(1001) 

実験2:

# In this case, we want the warning to come before code execution. This is easily fixed as shown below. 
# note: removed some extraneous useless stuff, the line to look for is sys.stderr.flush() 

from warnings import warn 
from warnings import resetwarnings 

class myClass(object):   
    def __init__(self, numberArg): 

     if numberArg > 1000: 
      self._tmpTxt = "That's a really big number for this code." + \ 
          "Code may take a while to run..." 
      warn("\n%s %s" %(numberArg, self._tmpTxt), category=Warning)    
      sys.stderr.flush()       # put this after each warn() to make it output more immediately 
      print("If this were real code:") 
      print("Actions code takes because this is a big number would happen here.") 

     print("If this were real code, it would be doing more stuff here ...") 

mc1 = myClass(1001) 

実験3:後でgithubの上でこのコードの

# code provided as an experiment ... may be updated later with a more useful example ... 
# in theory, filterwarnings should help shake out repeat warnings if used with right arguments 
# * note how our loop causes the content to print twice, and in theory, the 3 instances of warnings 
# * occur twice each for 6 possible output warnings 
# * each new occurance (3 of them) still outputs, but when the same ones come up again, they don't 
# * we get 3 instead of 6 warnings ... this should be the effect of filterwarning("once") 
#  in this instance 

# help on this: https://docs.python.org/3/library/warnings.html#warning-filter 
#    in this example: 
#     "once" arg = print only the first occurrence of matching warnings, regardless of location 

from warnings import warn 
from warnings import resetwarnings 
from warnings import filterwarnings 

class myClass(object):   
    def __init__(self, numberArg): 

     for i in [1,2]: 

      if numberArg > 1000: 
       print("loop count %d:" %(i)) 
       self._tmpTxt = "That's a really big number for this code." + \ 
           "Code may take a while to run..." 
       filterwarnings("once") 
       warn("\n%s %s" %(numberArg, self._tmpTxt), stacklevel=1, category=RuntimeWarning) 
       sys.stderr.flush() # this provides warning ahead of the output instead of after it 
       # resetwarnings() # no noticeable effect on the code 
       print("If this were real code:") 
       print("Actions code takes because this is a big number would happen here.") 

      if numberArg > 20000: 
       self._tmpTxt = "That's a really really really big number for this code." + \ 
           "Code may take a while to run..."     
       filterwarnings("once", "\nFW: %s %s" %(numberArg, self._tmpTxt)) 
       warn("\n%s %s" %(numberArg, self._tmpTxt), stacklevel=0) 
       # resetwarnings() # no noticeable effect on the code 
       sys.stderr.flush() # this provides warning ahead of the output instead of after it 

      print("loop count %d:" %(i))  
      print("If this were real code, it would be doing more stuff here ...") 

mc1 = myClass(1001) 
print("====================") 
mc2 = myClass(20001) 

ルック。 warningsの使い方を調べる他の人を助けるために、ここに投稿してください。

関連する問題