62564


Python3とPostgreSQLを利用して、WEBシステムを開発しています。

下記のように、リストに入っている値をfor文を使って、データベースに登録するためのコードを作成しました。

登録するテーブルのカラムはInteger型のため、str型のデータが含まれる場合は、try文でexcept処理して、次のfor文のループさせたいのですが、except処理される時に、for文の処理がとまってしまいます。

カラムの型に合わないデータは、except処理をして、さらにその後のfor文の動きを続けるには、どのようなコードにすれば良いのか、ご存じの方おりましたら、ご教授いただけないでしょうか？

●サンプルコード1

[code]

    import psycopg2
    
    
    sql_check1 = false
    sql_check2 = []
    
    conText = "host=localhost port=5432 dbname=sample user=user password=password"
    
    try:
        connection = psycopg2.connect(conText)
        cur = connection.cursor()
    except:
        sql_check1 = True
    
    #① int,int,str,intのリストを作成
    data_list[10,20,'error_data',30]
    
    for i in range(len(data_list)):
    
        try:
            #② Integer型のdataカラムにdata_listの値を保存したい
            sql = "INSERT INTO sample_table(data) VALUES(%s);"
            values = (data_list[i])
            cur.execute(sql, values)
    
            connection.commit()
    
        except:
            #③for文3回目（data_list[2]）の時にexceptの対象となる
            sql_check2.append(data_list[i])
            #④ここでfor文が止まってしまい、4回目のループに行かない
    
[/code]

開発環境  
Python: 3.7.5  
PostgreSQL: 12.1

* * *

**追記**  
●サンプルコード2

[code]

    import psycopg2
    
    sql_check1 = false
    sql_check2 = []
    cast_check = false  # 追記
    
    conText = "host=localhost port=5432 dbname=sample user=user password=password"
    
    try:
        connection = psycopg2.connect(conText)
        cur = connection.cursor()
    except:
        sql_check1 = True
    
    # ① int,int,str,intのリストを作成
    data_list[10, 20, 'error_data', 30]
    
    for i in range(len(data_list)):
    
        # 追記スタート
        try:
            int(data_list[i])
        except:
            cast_check = True
    　　　# 追記終了
    
        try:
            # ② Integer型のdataカラムにdata_listの値を保存したい
            sql = "INSERT INTO sample_table(data) VALUES(%s);"
            values = (data_list[i])
            cur.execute(sql, values)
    
            connection.commit()
    
        except:
            # ③for文3回目（data_list[2]）の時にexceptの対象となる
            sql_check2.append(data_list[i])
            # ④ここでfor文が止まってしまい、4回目のループに行かない
    
[/code]


CC BY-SA 4.0
2020-01-22T02:12:10.307
62446
2020-01-26T16:03:36.737
2020-01-22T03:41:27.247
36988
36988
question
python python3 postgresql
python3のfor文でDB接続のエラーが出ても、その後のループ処理を続けたい


  * `data_list` が作れていません。`data_list` は変数ですよね? 代入してください。
  * `values` はタプルです。例えば `(1,2,3)` はタプルです。要素が一つの場合には `(1)` としたいところですが、これだと式をまとめるただの括弧と区別が付かないので `(1,)` と書きます。同様に、`(data_list[i],)` とします。

たぶん、ここまでは質問にコードをコピペする時に間違ったのでしょう。重要なのはここからで、for は途中で止まってはいません。

  * 例外が本当に意図した時にだけ起きているかを確認するため、例外は受け取って出力してみるのが良いでしょう。
  * SQL の実行に失敗すると、トランザクションを継続することはできません。3番目と4番目は、間にトランザクションを分ける処理がないので、一つのトランザクションとなっています。従って、3番目で失敗すると、4番目は必ず失敗します。

1番目2番めで commit してトランザクションをそこで終了させるなら、3番目が失敗した時には rollback
でトランザクションを終了させるのが良いでしょう。そうすれば、4番目の SQL が実行できます。(といったことが、例外を出力してみるとわかります)。

結果として、コードは以下のようになります。

[code]

    #!/usr/bin/env python
    
    import psycopg2
    
    sql_check1 = False
    sql_check2 = []
    
    conText = "host=localhost port=5432 dbname=sample user=user password=password"
    
    try:
        connection = psycopg2.connect(conText)
        cur = connection.cursor()
    except:
        sql_check1 = True
    
    # ① int,int,str,intのリストを作成
    data_list = [10, 20, 'error_data', 30]
    
    for i in range(len(data_list)):
    
        try:
            # ② Integer型のdataカラムにdata_listの値を保存したい
            sql = "INSERT INTO sample_table(data) VALUES(%s);"
            values = (data_list[i],)
            cur.execute(sql, values)
    
            connection.commit()
    
        except Exception as e:
            print(e)
            # ③for文3回目（data_list[2]）の時にexceptの対象となる
            sql_check2.append(data_list[i])
            # ④ここでfor文が止まってしまい、4回目のループに行かない
            connection.rollback()
    
[/code]


CC BY-SA 4.0
2020-01-26T15:32:24.700
62564
2020-01-26T16:03:36.737
2020-01-26T16:03:36.737
5288
5288
62446
answer