在 psycopg2 中执行 sql 文件

Executing a sql file in psycopg2

这个功能或多或少是我们为服务台技术人员使用的实用程序的一部分,旨在为他们提供一种从 postgres 备份中提取 table 的简单方法,重命名 table 并将其重新插入到另一个数据库中。在使用 cur.execute() 将 table 实际插入所选数据库之前,我的函数一直运行良好。 sed(是的,我想坚持使用 sed)和提取部分效果很好。我想用 psycopg2 以某种方式执行文件,但如果有人有使用 subprocess 和 psql 的想法,我愿意接受其他建议。 使用 table 名称列表、目标数据库和 sql 文件备份调用此函数。我见过其他使用 .read() 的例子。我也知道我应该把文件名变成一个变量来稍微清理一下代码。如果可能,它还需要使用 python 2.6.

for tbl in selected_tables:
    # Open a file each iteration, dump the table in to it. Use .wait() to make sure the command finishes.
    table_file = open(str(tbl) + backup_suffix + ".sql", "w")
    p1 = subprocess.Popen(["/usr/bin/pg_restore", backup_picked, "-t", tbl], stdout=table_file)
    p1.wait()

    # Rename every instance of the table in the restore file. Format: _backup_YYYYMMDD
    sed_guts = "s/" + str(tbl) + "/"  + str(tbl) + backup_suffix + "/g"
    p2 = subprocess.Popen(["/bin/sed", "-i", sed_guts, str(tbl) + backup_suffix + ".sql"])
    p2.wait()
    table_file.close()

    # Restore the tables.
    try:
        # Gets the proper connection information. Works fine.
        site_config = site.ParseConfig(target_site)

        contents = open(str(tbl) + backup_suffix + ".sql", "r")


        con = psycopg2.connect(user=site_config['dbusername'],host=site_config['host'], \
                            password= site_config['password'], port=site_config['port'],\
                            dbname=site_config['dbname'])

        con.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)

        # Connect to postgres or to the db and then execute the query.
        cur = con.cursor()
        # Fails here
        cur.execute(contents.read())
        os.remove(str(tbl) + backup_suffix + ".sql")

    except:
        os.remove(str(tbl) + backup_suffix + ".sql")

最后我又回到了 psql 和 subprocess.Popen shell=True。这不是我的首选方法,因为我有其他限制,所以我愿意走这条路。如果有人好奇,这就是我所做的。

backup_suffix = site.FileSuffix(backup_picked)

# Do the actual restoration here. Use sed to rename every instance in the files that will be created below.
# Make sure the created files get removed before finishing.
for tbl in selected_tables:
    table_file_name = str(tbl) + backup_suffix + ".sql"

    # Open a file each iteration, dump the table in to it. Use .wait() to make sure the command finishes.
    table_file = open(table_file_name, "w")
    p1 = subprocess.Popen(["/usr/bin/pg_restore", backup_picked, "-t", tbl], stdout=table_file)
    p1.wait()
    table_file.close()

    # Rename every instance of the table in the restore file. Format: _backup_YYYYMMDD
    sed_guts = "s/" + str(tbl) + "/"  + str(tbl) + backup_suffix + "/g"
    p2 = subprocess.Popen(["/bin/sed", "-i", sed_guts, table_file_name])
    p2.wait()

    # Use psql to restore the tables.
    try:
        site_config = site.ParseConfig(target_site)
        dontuse, site_config = addFlags(site_config, site_config)

        command = '/usr/bin/psql %s %s %s %s < %s' % (site_config['host'], site_config['dbusername'],
                                                       site_config['dbname'], site_config['port'], table_file_name)

        p2 = subprocess.Popen('%s' % command, shell=True)
        p2.communicate()[0]

        os.remove(table_file_name)

    except:
        os.remove(table_file_name)
        session.CleanUp()

    exit(0)

还有多种方法可以在一个字符串中写入那么多变量。如果有人好奇,这里有一个 link 可以提供帮助: Using multiple arguments for string formatting in Python (e.g., '%s ... %s')

这是另一个用于在 Python 中打开和关闭文件的好资源: http://www.tutorialspoint.com/python/python_files_io.htm