【问题标题】:Using tempfile and subprocess in Python to transfer mysql into mongodbPython中使用tempfile和subprocess将mysql转入mongodb
【发布时间】:2013-08-16 20:53:12
【问题描述】:

我将使用pymysqltempfilesubprocess 编写一个脚本,将我的 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 操作之前尝试创建从另一个表派生的另一个文件(去进入下一次迭代,我的意思是),它还迫使我在整个过程完成后删除文件,所以我更喜欢使用临时文件而不是实际文件,但不完全确定我是否正确......

谢谢。

【问题讨论】:

  • 附带说明,fp.seek(0) 在这里没有任何用处;您没有将文件作为文件描述符传递给mongoimport,因此文件描述符中的位置指针无关紧要。

标签: python mongodb subprocess temporary-files


【解决方案1】:

tempfile.TemporaryFile 没有您可以获取的名称。特别是:

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

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

这正是tempfile.NamedTemporaryFile 的用途:

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


请注意,即使NamedTemporaryFile 也会在您关闭名称后立即取消链接,除非您传递delete=False。所以,你有两个选择:

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

【讨论】:

  • 谢谢。但随后它吐出一个错误:ERROR: file doesn't exist: /var/folders/3s/zvw8lr9575x7tlc1y9npb_040000gn/T/tmprj45fh。我不知道是什么导致了错误,但可能是因为我使用非阻塞subprocess.Popen?我很快会尝试阻塞版本的子进程,但我通常更喜欢非阻塞版本,如果使用tempfile 的非阻塞是可行的,那么我想接受它......
  • 啊,看来delete=False 参数解决了这里的问题,谢谢。
  • @user2360798:对tempfile 使用非阻塞可行的...但是在您确定子进程已打开文件之前,您无法删除该文件.你可以这样做,例如,传递delete=False,然后启动一个线程来观察孩子完成(或孩子的标准输出上的一些相关文本,或任何你能想到的),然后才删除文件。
  • @user2360798:仅使用delete=False 意味着您的临时文件永远不会被删除,直到您的操作系统的临时清理程序到达它为止。看起来您正在使用 OS X 的默认每用户温度,我认为在您注销并重新登录之前不会受到影响。这可以接受吗?
  • 是的,如果我退出后删除它,我会很满意。再次感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-25
  • 2013-08-15
  • 1970-01-01
  • 1970-01-01
  • 2019-08-02
相关资源
最近更新 更多