2012-04-24 9 views
0

私の関数の入力ファイルの規則のリストがあります。指定されたファイルに違反しているものがあれば、私のプログラムはエラーメッセージを返して終了します。真でない場合はエラーを返します(Python)

  • 最初の行は、すべての行が(0から数えて)正確に10列
  • カラム2を有していなければならない '#' 記号(ヘッダ行を示す)
  • で始まる必要があり、A +どちらかであるべきです - カラム8
として整数の正確に同じ数の、整数のコンマ区切りのリストであるべきシンボル
  • カラム8は整数
  • カラム9のカンマ区切りのリストであるべきです

    は、私は次のコードを書かれているこれを行うにしようとするには:

    編集stevehaの答えを

    with open(infile, 'r') as fp: 
    line = fp.readline().strip() 
    if not line.startswith('#'): 
        print ('First line does not start with #') 
        sys.exit(1) 
    n = 1 
    for line in fp.readlines(): 
        d = '(\d+,\d+)' 
        n += 1 
        cols = line.strip().split() 
        i = search(d, line) 
        if len(cols) != 10: 
         print('Lenth not equal to 10') 
         sys.exit(1) 
        if cols[2] != '+' or '-': 
         print('Column 2 is not a + or - symbol') 
         sys.exit(1) 
        if i and cols[8] != i.group(1): 
         print('Column 8 is not a comma-separated list of integers') 
         sys.exit(1) 
        if i and cols[9] != i.group(1) and len(cols[9]) != len(cols[8]): 
         print('Column 9 in not a comma-separated list of integers with the exact same number of integers in column 8') 
         sys.exit(1) 
    

    コードにしかし、私はこれを実行すると、すべての条件文は機能的であるように思われます。私はこれを正しくやろうとしているのですか?

  • +0

    どの条件が機能していませんか? (あなたの正規表現は整数の数ではなく、2つの整数だけをチェックすることに注意してください。)また、同じ数の整数が必要な場合は、列の長さに頼ることはできません。例えば'3,4'と' 30000,40000'は同じ数の整数を含みますが、異なる長さです。 (また、 '30000,40000'と' 3,4,5,6,7,8'は同じ長さですが、整数の数が異なります) –

    答えて

    3

    この行は間違っている:

    if cols[2] != '+' or '-': 
    

    これは正しいでしょう:

    if not (cols[2] == '+' or cols[2] =='-'): 
    

    私が代わりにこれをお勧めします。また

    if cols[2] not in ('+', '-'): 
    

    、私はあなたがfp.readlines()を呼び出すことはありませ示唆しています。ファイルオブジェクトfpはイテレータとして機能し、イテレータを繰り返すときには一度に1行しか取得できません。だからあなたのループはその後になる:

    for line in fp: 
    

    はまた、nのように見えるの行番号を追跡するのですか?

    for n, line in enumerate(fp, 1): 
    

    enumerate()はイテレータを取り、インクリメント数と一緒にイテレータから次の値を返します。その場合は、あなたがそうのように、それを行うことができます慣用Pythonの方法があります。デフォルトではカウントは0から始まりますが、開始番号を指定することもできます。

    そして、with文を使用してファイルを開くのがベストプラクティスです。

    with open(infile, 'r') as fp: 
        line = fp.readline().strip() 
        if not line.startswith('#'): 
         print ('First line does not start with #') 
         sys.exit(1) 
        for line in fp: 
         # process lines here 
    

    あなたが表示しているコードは完全にわかりません。この行:

    i = search(d, line) 
    

    すでにfrom re import searchコマンドを実行している必要があります。私は実際にimport reを実行してから、明示的にre.search()を呼び出すことをお勧めしますが、それは好みの問題です。とにかく、re.search()(または一致しない場合はNone)の一致グループの結果にiを設定します。しかし、後でコード内でではなくrをテストしています。ここに表示されているコードではrを決して設定しないので、そのことがどうなるか分かりません。個人的には、一致グループの変数名としてmを使用します。

    あなたの正規表現は、正の整数のペアにマッチします。そこにはどれだけの整数があるのか​​は決してありません。 cols[8]の文字数はlen(cols[8])で確認できます。

    文字列メソッド関数.split('')を呼び出していますが、これは正しくありません。私のシステムでは、例外が発生します:ValueError: empty separator.split()を呼び出して、空白で分割してください。カンマで区切られた整数リストに空白があってはならないと仮定します。

    最後に、PEP 8のガイドラインを考慮してください。変数FirstLineは、変数名ではなくクラス名のように大文字になります。それは私を正確に混乱させませんでしたが、それは気を散らすものでした。 PythonコミュニティのほとんどはPEP 8アカウントに上記のすべてを撮影

    http://www.python.org/dev/peps/pep-0008/

    を次の、私は単にあなたのコードを再書きました:

    import sys 
    
    def parse_list_of_int(s): 
        try: 
         return [int(x) for x in s.split(',')] 
        except Exception: 
         return None 
    
    with open("test.txt", 'r') as f: 
        # read line 1 
        line = f.readline().strip() 
        if not line.startswith('#'): 
         print ('First line does not start with #') 
         sys.exit(1) 
    
        # need to start enumerate() at 2 because we pulled line 1 out above 
        for i, line in enumerate(f, 2): 
         cols = line.strip().split() 
         if len(cols) != 10: 
          print('line {0}: Length not equal to 10'.format(i)) 
          sys.exit(1) 
         if cols[2] not in ('+', '-'): 
          print('line {0}: Column 2 is not a + or - symbol'.format(i)) 
          sys.exit(1) 
         lst8 = parse_list_of_int(cols[8]) 
         if lst8 is None: 
          print('line {0}: Column 8 is not a comma-separated list of integers').format(i) 
          sys.exit(1) 
         lst9 = parse_list_of_int(cols[9]) 
         if lst9 is None: 
          print('line {0}: Column 9 is not a comma-separated list of integers'.format(i)) 
          sys.exit(1) 
         if len(lst8) != len(lst9): 
          print('line {0}: Column 8 and column 9 do not have same number of integers'.format(i)) 
          sys.exit(1) 
    
    print('No problems!') 
    sys.exit(0) 
    

    私が出て解析する簡単な関数を書きました整数のリスト、Pythonリストを構築して返します。次に、コードは2つのリストが同じ長さであるかどうかを実際に正しく調べることができます。

    +0

    ありがとうございます、残りの部分は正しいようです。特にこの部分: 列8は、コンマで区切られた整数のリストでなければなりません 列9は、列8と全く同じ整数のカンマ区切りの整数リストでなければなりません。 –

    +0

    したがって、最初の行の条件付きで、 'n、line in enumerate(fp、1)、またはfpの行と同じように'と書くでしょうか? –

    +0

    あなたは正しいです、私は再輸入*から行った。変数がiだったので、後はr.searchからi.searchに変更する必要があります。私はあなたが記述したようにsplitメソッドも変更しました –

    関連する問題