如何获得完整性错误以继续插入db-python?

时间:2014-07-14 14:15:27

标签: python ruby-on-rails postgresql peewee

我有一个看起来像这样的postgres数据库:

                                                        Table "public.available_dates"
   Column   |            Type             |                          Modifiers                           | Storage | Stats target | Description
------------+-----------------------------+--------------------------------------------------------------+---------+--------------+-------------
 id         | integer                     | not null default nextval('available_dates_id_seq'::regclass) | plain   |              |
 unix_day   | integer                     |                                                              | plain   |              |
 hour       | integer                     |                                                              | plain   |              |
 created_at | timestamp without time zone |                                                              | plain   |              |
 updated_at | timestamp without time zone |                                                              | plain   |              |
Indexes:
    "available_dates_pkey" PRIMARY KEY, btree (id)
    "index_available_dates_on_unix_day_and_hour" UNIQUE, btree (unix_day, hour)
    "index_available_dates_on_unix_day" btree (unix_day)
Has OIDs: no

这是我开发的rails应用程序和作为服务运行的python应用程序,我使用peewee作为python的orm。 rails app运行正常,我需要这个db上的每个索引。

python应用程序查看文件,并向db添加日期。我遇到的问题是如果日期+小时存在,它会失败并结束python应用程序。我不想在数据库中使用dupes,但如果抛出此完整性错误,我还希望应用程序继续运行。这是我到目前为止的代码:

data_source = [{'unix_day': 1370044800, 'created_at': datetime.datetime(2014, 7, 14, 10, 12, 57, 488000), 'updated_at': datetime.datetime(2014, 7, 14, 10, 12, 57, 488000), 'hour': 1}, 
...
]

        try:
            with db.transaction():
                Available_Dates.insert_many(data_source).execute()
        except IntegrityError as e:
            print e
            db.rollback()
            pass
        else:
            db.commit()
        db.close()

哪个失败了(应该如此):

重复键值违反了唯一约束" index_available_dates_on_unix_day_and_hour"     DETAIL:Key(unix_day,hour)=(1370044800,10)已经存在。

如何让我的代码说出来,"那失败了?哦,好吧......我只是尝试下一个。"

注意:我预计它会失败而不是成功。

编辑:第一个答案的选项1:

for data in data_source:
            try:
                av_date = Available_Dates()
                av_date.unix_day = data['unix_day']
                av_date.hour = data['hour']
                av_date.created_at = data['created_at']
                av_date.updated_at = data['updated_at']
                av_date.save()

            except Exception as e:
                pass

这似乎不太好,因为我捕捉到了所有异常...而且,我必须分别分配每个成员,这似乎效率低下。它也失败了因为db上有锁。

duplicate key value violates unique constraint "index_available_dates_on_unix_day_and_hour"
DETAIL:  Key (unix_day, hour)=(1370044800, 1) already exists.

current transaction is aborted, commands ignored until end of transaction block

current transaction is aborted, commands ignored until end of transaction block

current transaction is aborted, commands ignored until end of transaction block

current transaction is aborted, commands ignored until end of transaction block

current transaction is aborted, commands ignored until end of transaction block
 ...

3 个答案:

答案 0 :(得分:1)

我认为如果您使用单个函数插入所有内容,insert_many在这种情况下,这会使面临异常时更难以继续。我的建议是在for循环中一次插入一个项目,并将每个插入包装在try-except而不是整个内容中。

答案 1 :(得分:0)

这就是我所做的(感谢ZJS):

for data in data_source:
            try:
                exists = Available_Dates.get(Available_Dates.unix_day == data['unix_day'],
                                             Available_Dates.hour == data['hour'])
            except Available_Dates.DoesNotExist:
                av_date = Available_Dates.create(**data)
                print av_date.id, "added to the database."
            except Exception as e:
                print e, type(e)
                pass

答案 2 :(得分:0)

我正在这样做,以防它有用

data = [(a,b), (a,b), (a,b)]

with database.atomic():
    # try bulk
    try:
        MyModel.insert_many(data, fields=[MyModel.field1, MyModel.field2]).execute()
    # if it fails, switch to individually adding (slower)
    except IntegrityError:
        for d in data:
            try:
                entry = MyModel(
                    field1=d[0],
                    field2=d[1],)
                entry.save()
            except IntegrityError:
                pass