2

次のディレクトリ/ファイルのセットアップがあります (これは簡略化されています)。

Ce  
+---top.txt
+---X0.0        
|     |  
|     +---Y0.0  
|     |     |
|     |     +---X0.0Y0.0Z0.0.dat
|     |     +---X0.0Y0.0Z0.05.dat   
|     +---Y0.05
|           |
|           +---X0.0Y0.05Z0.0.dat
|           +---X0.0Y0.05Z0.05.dat
+---X0.05
      |  
      +---Y0.0  
      |     |
      |     +---X0.0Y0.0Z0.0.dat
      |     +---X0.0Y0.0Z0.05.dat   
      +---Y0.05
            |
            +---X0.0Y0.05Z0.0.dat
            +---X0.0Y0.05Z0.05.dat

各 Y ディレクトリ内で、.dat ファイルのリストをファイル「top.txt」のコピーに追加する「psub」ファイルを作成する必要があります。

Python 3 で os.walk 関数を使用してこれを実行しようとしています: ただし、2 つの問題が発生しています:
1. 新しい psub ファイルが X0.0 ディレクトリに表示される
2. コードにファイル名が表示されない (おそらくX0.05 ディレクトリが見つからないというエラーが表示されます。

これまでのところ、次のコードがあります。

import os

with open('top.txt', 'r') as reader:
    data=reader.read()
    for root, dirs, files in os.walk('.'):
        for folder in dirs:
            os.chdir(os.path.join(root, folder))
            with open('psub', 'a') as writer:
                writer.write(data)
                for names in files:
                    if names.endswith('.dat'):
                        print('gulp <' + names + '> ', end='', file=writer)
                        print(names.rsplit('.',1)[0], end='', file=writer)
                        print('.out', file=writer)

結果の psub ファイルは次のようになります。

#!/bin/bash
#MOAB -l walltime=48:00:0
#MOAB -j oe
#MOAB -N GULP-job
cd "$PBS_O_WORKDIR"
module load apps/gulp
#!/bin/bash
gulp <X0.00Y0.00Z0.00.dat> X0.00Y0.00Z0.00.out
gulp <X0.00Y0.00Z0.05.dat> X0.00Y0.00Z0.05.out

最初の 7 行は top.txt にあります。

私がどこで間違っているかについての(単純な)ポインタは大歓迎です。乾杯

4

1 に答える 1

4

walkすべてのディレクトリを再帰的に繰り返すことを意図しているため、すべてのサブディレクトリを自分で繰り返す必要はありません。for folder in dirs:ループを取り除きます。

また、次のように、複数の print ステートメントを単一の文字列形式コマンドに置き換えることもお勧めします。

print('gulp <{}.dat> {}.out'.format(names.rsplit('.',1)[0]), file=writer)
#or use writer.write(), to make it more transparent

また、いくつかの変数の名前を変更して、その使用目的をより適切に表す必要があります。たとえば、最後のループで繰り返し変数を呼び出すと、names実際には名前のコレクションではなく、単一のファイル名であるため、誤解を招く可能性があります。

編集:余分な空のファイルを作成しないようにするには、ディレクトリにファイルを作成する必要があるかどうかを確認する必要があります。これを行うには、ファイル名を繰り返し処理し、処理が必要なファイルがある場合はフラグを設定し.datます。

EDIT 2:コードを分解し、多くのものの名前を変更したため、より明確になりました。

これらの変更を合計すると、次のようになります。

import os

def isDat(filename): return filename.endswith('.dat')

def hasDat(filenames): #this method checks if it contains one ending with '.dat'
    for filename in filenames:
        if isDat(filename): return true
    return false

def datFiles(filenames):
    for filename in filenames:
        if isDat(filename): yield filename

def gulpLines(filenames):
    for filename in datFiles(filenames):
        yield 'gulp <{}.dat> {}.out\n'.format(filename.rsplit('.',1)[0])

def makePsub(root, filenames, prologue):
    with os.open(os.path.join(root, 'psub'), 'a') as writer:
    #try putting 'psub.sh' instead, perhaps it is getting confused with no extension
        writer.write(prologue)
        for gulpLine in gulpLines(filenames):
            writer.write(gulpLine)


with open('top.txt') as reader:
    prologue=reader.read() #this is a much more descriptive name
#you can close it as soon as you have its contents

for root, dirs, filenames in os.walk('.'):
    if hasDat(filenames):
        makePsub(root, filenames, prologue)

Python は、20 の深さでネストされた巨大で長い怪物ではなく、多数の小さな関数で構成されることを意図しています。

さらに、コードを分解することで、コードのどの部分が問題を引き起こしているかを正確に判断できます。これは、各機能を個別にテストできるためです。.datたとえば、ファイルを正しく認識できないことが問題であると思われる場合は、問題がisDat修正されるまで機能を単独でテストできます。問題がファイルへの書き込みにあると思われる場合は、ダミーの実装 (事前に定義された結果のリストを使用するか、実際に結果を生成するのではなく、ユーザーに手動で実行させる) にpsub置き換えることで確認できます。gulpLines

他にできることは、ループ内にデバッグ コードを挿入することです。たとえば、writer(おそらく) 書き込んだ後にの内容を出力するステートメントを挿入dataして、期待どおりのものが実際にあるかどうかを確認します。もう 1 つのデバッグ オプションは、部分的なコードを実行することです。たとえば、ウォーク ループのみを実行するdata、ファイルへの書き込みのみを行う、またはファイル名の解析のみを行うプログラムを実行します (検査目的で、ファイルに書き込む内容をコンソールに出力します)

于 2013-09-16T14:56:57.017 に答える