1

昨夜、コメント行をすべてファイルから取り出して新しいファイルに出力するプログラムを書きました。これは、私のプログラミングの授業で頻繁にやらなければならないことで、コピーと貼り付けでファイルを選択するのはすぐに慣れてしまいます。

入力ファイルと出力ファイルの両方が存在するかどうかを確認しています。入力ファイルが存在する場合は、すべて続行します。存在しない場合は、別のファイル名を尋ねます。出力ファイルが存在する場合は、上書きするかどうかをユーザーに尋ねます。存在しない場合は、すべて続行します。

私が抱えている問題は、file = open(fileName, 'r') がファイルを見つけられない場合に 1 つのチェックが正しく IOError をスローし、もう 1 つのチェックが IOError を与える代わりに空のファイルを作成することです。

2 ビットのコードがほとんど同じであるため、これは特に不可解です。同じプロセスで、ファイル名変数が異なるだけです...

コードは以下です。2 番目の部分は、空のファイルを作成する部分です。最初に期待どおりにエラーが発生します。

# Try to open the input file
inFileOpen = False
while not inFileOpen and userTrying:
    # If it opens, all good
    try:
        inFile = open(inFileName, 'r')
        inFileOpen = True
    # If it doesn't open, ask user to try a different file
    except IOError:
        ...

# Try to open the output file
toFileOpen = False
while not toFileOpen and userTrying:
    # If the file opens in r mode, that means it exists already, so ask user if they
    # want to overwrite the existing file, if not ask for a new file name
    try:
        # ********************
        # For some reason, 'r' mode is creating a file... no clue...
        # ********************
        toFile = open(toFileName)
        toFile.close() # I have tried removing this just guessing at solutions. Didn't work.

        # ... Ask if user wants to overwrite

    # If the file can't be opened, all good, that means it doesn't exist yet
    except IOError:
        toFileOpen = False
        toFile = open(toFileName, 'w')
4

2 に答える 2

2

Python 3.3 を使用している場合は、ファイルが既に存在openする場合に a が発生することを除いて、「w」と同じ「x」モードがあります。FileExistsExceptionこれは、ファイルが存在するかどうかのテストと書き込み用にファイルを開く間の原子的で免疫的な競合状態であるため、個別のチェックよりも優れています。これはおそらく現在のスクリプトの問題ではありませんが、よりセキュリティ クリティカルなプログラムでは問題になる可能性があります。

古いバージョンの Python (2.x および 3.0-3.2) では、もう少し注意が必要です。1 つのオプションは、ファイルを追加用に開き ("a" モード)、現在のストリーム位置を ( を使用してtell) 調べて、既に何かが含まれているかどうかを確認することです。変更されたが、ユーザーが古い内容を置き換えたい場合は、 を呼び出しtruncate()seek(0)現在のデータを消去し、ファイルの先頭に戻ることができます。これにより、長さ 0 のファイルが予告なしに上書きされる可能性は依然としてありますが、それは大きな問題ではないと思います。もう 1 つの方法は、os.O_EXCL|os.O_CREATフラグを明示的にos.openに渡し、返されたファイル記述子を に渡してos.fdopen、通常の Python ファイル オブジェクトを取得することです。これは基本的に、「x」モードが舞台裏で行うことです。

編集:これは、ユーザーとの実際の対話を行う適切な機能get_filenameと機能が与えられた出力ファイルを作成するための気の利いたコンテキストマネージャーソリューションです。confirm_overwriteこのコードは Python 3.3 用ですが、以前のバージョンで動作するようにopen呼び出しとおそらくexceptステートメントを変更できます。

from contextlib import contextmanager

@contextmanager
def create_output_file():
    while True:
        out_filename = get_filename()

        try:
            with open(out_filename, "x") as f:
                yield f
            break

        except FileExistsException:
            if confirm_overwrite(out_filename):
                with open(out_filename, "w") as f:
                    yield f
                break

with次のステートメントで使用します。

with create_output_file() as f:
    f.write("whatever")
于 2012-11-11T22:48:01.050 に答える
1

os.path.exists(filename) はファイルをチェックする良い方法だと思います:

例えば。

 while not os.path.exists(infile):
     infile = askfilename()
 with open(infile) as f:
     for line in f:
         ...

出力ファイルについても同様のことができます

于 2012-11-11T22:51:22.647 に答える