调用pg_dump时对pexpect感到奇怪

时间:2019-07-18 04:47:10

标签: python pexpect pg-dump

很抱歉,如果不允许这样做,我仍然是新手,因此请您原谅我。我对自己注意到的行为感到好奇,并希望获得一些建议。

在调用pg_dump时,您现在似乎需要传递用户提升的密码,因此我在这里的选项受到限制,并且use选项正在使用pexpect来传递短语。

尽管,在发送完该行之后,什么也没有发生,并且当登录到文件时,我所看到的只是正在发送的密码,但是没有输出。我对命令进行了两次/三次检查,它可以正常工作(使用cli),因此下面的代码片段应该可以正常工作。

我尝试child.logfile_read确定期望的输出,而我的child.expect也正确。

password='test'
cmd = 'pg_dump --host {host} --port {port} --dbname {db} --username {username}\
    --file {filename} --table {table} --schema={schema}'.format(
        host=host,
        port=port,
        db=db,
        username=username,
        filename=filename,
        table=table,
        schema=schema
    )


child = pexpect.spawn(cmd)
child.expect('Password:')
child.sendline(password)
child.read()

我只是发生以添加一个child.read()并繁荣,我的文件已按预期导出。这对我来说是错的,我尝试了几种不同的方法并通读了文档,但是我似乎无法完全相信这一事实。我的意思是,根据documentation

  

这将从文件中读取最多“大小”字节(如果读取在获得大小字节之前达到EOF,则更少)。如果size参数为负或省略,则读取所有数据,直到达到EOF。字节作为字符串对象返回。立即遇到EOF时,将返回一个空字符串

为什么这实际上起作用?我想念什么?我觉得这些都是后来要轰炸我的例子之一,因为我实际上并不了解幕后发生的事情。

我的最佳猜测是EOF发生了一些奇怪的事情,该命令实际上并未得到处理,但是一旦我使用child.read(),它实际上就在完成命令了吗?不确定,说实话。

1 个答案:

答案 0 :(得分:1)

关键字是EOF。

正如您发布的pexpect文档摘录所暗示的那样,read读取指定的字节数,或者直到遇到EOF。在您的上下文中,这意味着子进程等待发送EOF,等效于进程终止。

在没有调用read的情况下,子进程完成之前,Python进程不会阻塞。它在child.sendline(password)调用返回后立即结束。

从您使用spawn的事实来看,我假设您正在POSIX平台上运行它。这就是说,预期孩子is an instance of ptyprocess.PtyProcessPtyProcess类实现了__del__终结器,旨在...

  

[...]确保没有打开任何系统资源。

实例上的终结器callsclose方法。这将关闭文件描述符,并通过SIGINT,SIGHUP或如果最终通过force=True(默认)调用SIGKILL来调用terminate结束子进程。

因此,当您的Python进程结束时,在child.sendline(password)返回之后,解释器立即开始清理其内存空间并在进程中执行终结器。这会在您的pg_dump命令开始写入输出文件之前就终止执行。

您必须阻塞主进程,直到子进程完成。 read确实可以这样做,但是您似乎对从孩子那里读书并不特别感兴趣。您可以改为使用wait()

  

这将等待直到孩子退出。这是一个阻止呼叫。这不会从子[...]

中读取任何数据