2

私: アップグレードの可能性なしで Python 2.3.3 を実行しています。Python の経験はあまりありません。私の学習方法は、グーグルで調べて大量のスタックオーバーフローを読むことです。

背景: 2 つのディレクトリを引数として取り、2 つのディレクトリ内で見つかったすべてのファイルの比較/差分を実行することを目的とした python スクリプトを作成しています。ディレクトリにはサブディレクトリがあり、これも差分に含める必要があります。各ディレクトリはリストであり、サブディレクトリはネストされたリストなどです...

the two directories:
oldfiles/
    a_tar_ball.tar
    a_text_file.txt
    nest1/
        file_in_nest
        nest1a/
            file_in_nest

newfiles/
    a_tar_ball.tar
    a_text_file.txt
    nest1/
        file_in_nest
        nest1a/

問題: oldfiles 内のすべてのファイルは newfiles に存在するはずなので、通常はすべてうまくいくはずですが、上記の例では、'file_in_nest' の 1 つが 'newfiles/' にありません。どのファイルが欠落しているかを知らせるエラー メッセージを出力したいのですが、「比較」関数の現在のインスタンスの下にあるコード構造を使用している場合、最も近いディレクトリ以外のディレクトリはわかりません。ファイルとディレクトリに関する情報を再帰ラダーに送信して、情報を追加するエラー処理が組み込まれているのではないかと思います。「oldfiles」には2つの「file_in_nest」があるため、欠落しているファイルのファイル名を印刷するだけでは、どれがどれであるかわかりません

def compare(file_tree)
    for counter, entry in enumerate(file_tree[0][1:]):
        if not entry in file_tree[1]
            # raise "some" error and send information about file back to the 
            # function calling this compare, might be another compare.
        elif not isinstance(entry, basestring):
            os.chdir(entry[0])
            compare(entry)
            os.chdir('..')
        else:
            # perform comparison (not relevant to the problem)

        # detect if "some" error has been raised
            # prepend current directory found in entry[0] to file information
            break

def main()
    file_tree = [['/oldfiles', 'a_tar_ball.tar', 'a_text_file.txt', \
                [/nest1', 'file_in_nest', [/nest1a', 'file_in_nest']], \
                'yet_another_file'], \
                ['/newfiles', 'a_tar_ball.tar', 'a_text_file.txt', \
                [/nest1', 'file_in_nest', [/nest1a']], \
                'yet_another_file']]

    compare(file_tree)

    # detect if "some" error has been raised and print error message

これは、読む以外のスタックオーバーフローでの私の最初の活動です。質問を改善する必要があるかどうか教えてください!

// ステファン

4

1 に答える 1

1

エラーを例外として報告するか、何らかの形式のステータスとして報告するかによって異なります。

「例外」の方法に進み、1 つのファイルが欠落している場合にプログラム全体をクラッシュさせたいとしましょう。呼び出し先から呼び出し元に状態を保存する独自の例外を定義できます。

class PathException(Exception):
    def __init__(self, path):
        self.path = path
        Exception.__init__(self)

def compare(filetree):
    old, new = filetree
    for counter, entry in enumerate(old[1:]):
        if entry not in new:
            raise PathException(entry)
        elif not isinstance(entry, basestring):
            os.chdir(entry[0])
            try:
                compare(entry)
                os.chdir("..")
            except PathException as e:
                os.chdir("..")
                raise PathException(os.path.join(entry, e.path))
        else:
            ...

try再帰呼び出しを行い、着信例外を呼び出し元の情報で更新します。

より小さな例でそれを見るために、2 つのリストを深く比較して、それらが等しくない場合に例外を発生させてみましょう。

class MyException(Exception):
    def __init__(self, path):
        self.path = path
        Exception.__init__(self)

def assertEq(X, Y):
    if hasattr(X, '__iter__') and hasattr(Y, '__iter__'):
        for i, (x, y) in enumerate(zip(X, Y)):
            try:
                assertEq(x, y)
            except MyException as e:
                raise MyException([i] + e.path)
    elif X != Y:
        raise MyException([]) # Empty path -> Base case

これにより、次のことがわかります。

>>> L1 = [[[1,2,3],[4,5],[[6,7,8],[7,9]]],[3,5,[7,8]]]
>>> assertEq(L1, L1)

何も起こりません (リストは同様です)。

>>> L1 = [[[1,2,3],[4,5],[[6,7,8],[7,9]]],[3,5,[7,8]]]
>>> L2 = [[[1,2,3],[4,5],[[6,7,8],[7,5]]],[3,5,[7,8]]] # Note the [7,9] -> [7,5]
>>> try:
...     assertEq(L1, L2)
... except MyException as e: 
...     print "Diff at",e.path
Diff at [0, 2, 1, 1]
>>> print L1[0][2][1][1], L2[0][2][1][1]
9 5

これにより、フルパスが得られます。

再帰リストまたはパスは基本的に同じものであるため、ユースケースに簡単に適応させることができます。

これを解決するもう 1 つの簡単な方法は、ファイルのこの違いを他のファイルと同様の単純な diff として報告することです。古いファイルと (存在しない) 新しいファイルの違いとして返すか、両方のリストを返すことができます。ファイルの相違点とファイルの相違点リスト。この場合、再帰呼び出しによって返される値を再帰的に更新するのは簡単です。

于 2013-11-12T17:39:55.833 に答える