在 python 中的上下文管理器之前或之后循环

Looping before or after context manager in python

我在 Whosebug 上搜索过,找不到任何相关的标题。 假设在 python 中我想连接到数据库并执行一些查询。这是最好的方法。在循环内声明with语句还是在循环外?它通常也适用于处理文件。为了更清楚起见,请参阅以下 2 个变体。

此外,我想知道找到 try 和 except 语句的更好方法,应该是在启动上下文管理器之前还是之后(正如我在下面所做的那样)。

在循环之前有语句

def wr_to_db(db_file):
    query_switch = 'insert into switches values (?, ?)'
    with sqlite3.connect(db_file) as conn:
        for data in read_switch_data():
            try:
                conn.execute(query_switch, data)
            except sqlite3.IntegrityError as e:
                print('Error occured: ', e)

在循环后有语句

def wr_to_db(db_file):
    query_switch = 'insert into switches values (?, ?)'
    for data in read_switch_data():
        with sqlite3.connect(db_file) as conn:
            try:
                conn.execute(query_switch, data)
            except sqlite3.IntegrityError as e:
                print('Error occured: ', e)

(我很惊讶没有人回答这个...)
我认为您的第一个示例非常准确:您希望 with() 语句位于 for 循环之外。 with 上下文管理器很有用,因为它会在您退出该块时自动清理资源(关闭打开的文件,或 closes/flushes 建立的数据库连接)。因此,如果您以第二种方式执行此操作并将上下文管理器 放在 for 循环中,您将连接到数据库并在每个循环中关闭+清理该连接。这是非常低效的。

此外,您还询问了 try/except 个区块。同样,您希望上下文管理器围绕整个块。但是相对于您的 for 循环将它们放置在何处取决于您希望在异常情况下发生什么。以这两种情况为例(我们假设我们已经为每种情况建立了数据库连接):

with sqlite3.connect(db_file) as conn:
    for data in read_switch_data():
        try:
            conn.execute(query_switch, data)
        except sqlite3.IntegrityError as e:
            print('Error occured: ', e)

对比

with sqlite3.connect(db_file) as conn:
    try:
        for data in read_switch_data():
            conn.execute(query_switch, data)
    except sqlite3.IntegrityError as e:
        print('Error occured: ', e)

第一种情况,如果在执行一条语句时出错,会打印错误,然后继续尝试下一条语句。在第二种情况下,如果引发异常,那么它将打印错误并退出整个循环,并且不再尝试 execute 命令。所以放置取决于你希望它如何表现。

希望对您有所帮助,编码愉快!