1

うまく機能する2つの関数がありますが、それらをネストして実行すると機能しなくなるようです。

def scrape_all_pages(alphabet):
    pages = get_all_urls(alphabet)
    for page in pages:
        scrape_table(page)

いくつかの検索結果を体系的に取得しようとしています。したがってget_all_pages()、アルファベットの各文字のURLのリストを作成します。何千ものページがあることもありますが、それは問題なく機能します。次に、ページごとに、scrape_table関心のあるテーブルだけをスクレイプします。これも問題なく機能します。すべてを実行でき、正常に動作しますが、Scraperwikiで作業しており、実行して離れるように設定すると、必ず「リストインデックスが範囲外です」というエラーが発生します。try/exceptこれは間違いなくscraperwiki内の問題ですが、いくつかの句を追加し、それらに遭遇したときにエラーをログに記録することによって、問題に焦点を当てる方法を見つけたいと思います。何かのようなもの:

def scrape_all_pages(alphabet):
    try:
        pages = get_all_urls(alphabet)
    except:
        ## LOG THE ERROR IF THAT FAILS.
    try:
        for page in pages:
            scrape_table(page)
    except:
        ## LOG THE ERROR IF THAT FAILS

ただし、エラーを一般的にログに記録する方法を理解できていません。また、上記は不格好に見えます。私の経験では、何かが不格好に見える場合、Pythonの方が優れています。もっと良い方法はありますか?

4

5 に答える 5

2

要件に合わせて詳細を簡単に変更できますが、このようにログ情報をコンテキストマネージャーにラップします。

import traceback

# This is a context manager
class LogError(object):
    def __init__(self, logfile, message):
        self.logfile = logfile
        self.message = message
    def __enter__(self):
        return self
    def __exit__(self, type, value, tb):
        if type is None or not issubclass(type, Exception):
            # Allow KeyboardInterrupt and other non-standard exception to pass through
            return

        self.logfile.write("%s: %r\n" % (self.message, value))
        traceback.print_exception(type, value, tb, file=self.logfile)
        return True # "swallow" the traceback

# This is a helper class to maintain an open file object and
# a way to provide extra information to the context manager.
class ExceptionLogger(object):
    def __init__(self, filename):
        self.logfile = open(filename, "wa")
    def __call__(self, message):
        # override function() call so that I can specify a message
        return LogError(self.logfile, message)

重要な部分は、__exit__が「True」を返すことができることです。この場合、例外は無視され、プログラムは続行されます。また、KeyboardInterrupt(control-C)、SystemExit、またはその他の非標準の例外が発生する可能性があり、実際にプログラムを停止させたい場合は、コードに少し注意する必要があります。

あなたはこのようにあなたのコードで上記を使うことができます:

elog = ExceptionLogger("/dev/tty")

with elog("Can I divide by 0?"):
    1/0

for i in range(-4, 4):
    with elog("Divisor is %d" % (i,)):
        print "5/%d = %d" % (i, 5/i)

そのスニペットは私に出力を与えます:

Can I divide by 0?: ZeroDivisionError('integer division or modulo by zero',)
Traceback (most recent call last):
  File "exception_logger.py", line 24, in <module>
    1/0
ZeroDivisionError: integer division or modulo by zero
5/-4 = -2
5/-3 = -2
5/-2 = -3
5/-1 = -5
Divisor is 0: ZeroDivisionError('integer division or modulo by zero',)
Traceback (most recent call last):
  File "exception_logger.py", line 28, in <module>
    print "5/%d = %d" % (i, 5/i)
ZeroDivisionError: integer division or modulo by zero
5/1 = 5
5/2 = 2
5/3 = 1

IndexError例外のみのログを処理するように、またはキャッチするために基本例外タイプを渡すようにコードを変更する方法も簡単に理解できると思います。

于 2012-11-25T20:16:07.683 に答える
2

キャッチする特定のタイプの例外と、例外インスタンスを保持する変数を指定できます。

def scrape_all_pages(alphabet):
    try:
        pages = get_all_urls(alphabet)
        for page in pages:
            scrape_table(page)
    except OutOfRangeError as error:
        # Will only catch OutOfRangeError
        print error
    except Exception as error:
        # Will only catch any other exception
        print error

タイプ Exception をキャッチすると、おそらくすべて Exception から継承されているため、すべてのエラーがキャッチされます。

これは、エラーをキャッチするために私が知っている唯一の方法です。

于 2012-11-25T19:44:21.820 に答える
0

1 回の反復でエラーが発生してもループが壊れないように、反復ごとにエラーをログに記録してください。

for page in pages:
    try:
        scrape_table(page)
    except:
        #open error log file for append:
        f=open("errors.txt","a")
        #write error to file:
        f.write("Error occured\n") # some message specific to this iteration (page) should be added here...
        #close error log file:
        f.close()
于 2012-11-25T19:45:56.650 に答える
0

いい方法ですが。justexcept句を使用しないでください。キャッチしようとしている例外のタイプを指定する必要があります。また、エラーをキャッチしてループを続行することもできます。

def scrape_all_pages(alphabet):
    try:
        pages = get_all_urls(alphabet)
    except IndexError: #IndexError is an example
        ## LOG THE ERROR IF THAT FAILS.

    for page in pages:
        try:
            scrape_table(page)
        except IndexError: # IndexError is an example
            ## LOG THE ERROR IF THAT FAILS and continue this loop
于 2012-11-25T19:46:54.290 に答える
0

次のように書いたほうがいいです。

    try:
        pages = get_all_urls(alphabet)
    except IndexError:
        ## LOG THE ERROR IF THAT FAILS.
    for page in pages:
        try:
            scrape_table(page)
        except IndexError:
            continue ## this will bring you to the next item in for
        ## LOG THE ERROR IF THAT FAILS
于 2015-07-29T11:51:17.287 に答える