2

我将使用pymysql,tempfilesubprocess编写一个将我的 MySQL 数据库传输到 MongoDB 的脚本,但到目前为止我还没有做好。

在以下代码中:

for table_name in table_list:
    cur.execute("select * from {0};".format(table_name))
    with tempfile.TemporaryFile(mode='w+') as fp:
        writer = csv.writer(fp)
        writer.writerow([i[0] for i in cur.description])
        for record in cur.fetchall():
            writer.writerow(record)

        fp.seek(0)
        subprocess.Popen(['mongoimport', '-d', db_mongo, '-c', table_name, '--type', 'csv', '--file', *** I don't know what should be specified here ***, '--headerline'])

我尝试迭代任何mysql数据库的表名,从表中选择所有数据,将结果写入临时文件,然后使用mongoimport将文件中的数据倒入mongodb数据库。subprocess.Popen但是,一,我不知道如何在函数中指出文件名。二、有没有更好的方法来做我想做的事?我认为有,但在我的脑海中想不出比这更好的一个......

供您参考,我最初使用实际(不是临时)文件名,但如果表太大,它会失败,因为它会在完成前一个表的subprocess.Popen操作之前尝试创建另一个从另一个表派生的文件(我的意思是进入下一次迭代) ,并且它还迫使我在整个过程完成后删除文件,所以我更喜欢使用临时文件而不是实际文件,但不完全确定我是否正确......

谢谢。

4

1 回答 1

3

tempfile.TemporaryFile没有你能得到的名字。尤其是:

在 Unix 下,文件的目录条目在文件创建后立即被删除。

在其他平台上,文件可能有也可能没有目录条目,但您仍然无法从 API 获取它。

这正是tempfile.NamedTemporaryFile为了:

这个函数的操作和原来的完全一样TemporaryFile(),除了保证文件在文件系统中有一个可见的名字(在 Unix 上,目录条目没有被取消链接)。该名称可以从name文件对象的属性中检索。


请注意,即使NamedTemporaryFile您关闭该名称,它也会取消链接,除非您通过delete=False. 所以,你有两个选择:

  • 在将来的某个时候使用delete=False并依赖操作系统来清理文件。(在 OS X 上,使用默认的每用户临时系统,我相信该文件夹将在下次注销或下次登录时被扫描和清理,这个人不会很长时间。)
  • 等到子进程打开文件后再关闭它。显而易见的方法是使用阻塞subprocess.check_call或类似方法,而不是仅仅触发和忘记 a Popen,但如果你想变得更狡猾,你可以。例如,您可以在后台线程中进行等待和删除。或者,如果此脚本是更大的脚本套件的一部分,您可以让它向上传递临时路径(通过标准输出、文件等)并让最后一个脚本清理所有文件。或者您可以找到一种方法来等待文件打开,而不是等待整个过程完成。或补丁mongoimport添加一个--unlink-input-file标志。或者……</li>
于 2013-08-16T21:29:14.233 回答