【问题标题】:Writing to a file from a subprocess and parent process simultaneously同时从子进程和父进程写入文件
【发布时间】:2016-06-30 21:17:33
【问题描述】:

我有一个脚本 (Python),它使用子进程调用另一个脚本。父脚本同时写入控制台和日志文件(我使用this question接受的答案中的代码来拆分输出),但子进程打印语句只会写入标准输出,不会写入日志文件。

我确实知道这是为什么:子进程将标准输出设置为普通标准输出,而不是父进程具有的特殊 tee 对象。我尝试将 tee 对象作为参数传递给子进程,但我学到了不能将对象作为参数传递给子进程的艰难方法。我的备份计划是传入要写入的文件的路径字符串,然后让子进程使用同一个文件创建自己的 tee 对象。

我的问题是,如果两个进程同时写入同一个文件,输出会不会混乱?我在父进程中使用 open("file", 'w') ,首先调用它,我在子进程中使用 open("file", 'a') 。假设,该文件应该以正确的顺序包含打印语句的输出,因为附加到带有“a”的文件意味着这些行将始终添加到当前文件的末尾,不是吗?或者是否有关于打开文件的规则阻止它被2个进程同时打开?

POST_TEST:我自己做了一些测试后,发现如下: -您可以连续多次打开("file", 'w') - 你可以先打开("file", 'w') 然后再打开("file", 'a') -在第一种情况下,子进程完全覆盖文件。 -第二种情况,顺序不正确,好像丢失了一些输出。

然后我的新问题是,我应该使用什么替代解决方案同时从父进程和子进程写入文件,而不会出现乱序或重叠的行?

【问题讨论】:

  • 谷歌“互斥锁”。互斥锁是对资源的互斥锁,可避免两个进程使用同一资源时发生冲突。
  • a模式打开的进程总是会写在文件的末尾。但是以w 模式打开的那个不会。您需要在a 模式下打开它们。
  • @JuanTomas 实际上我去年在 C++ 课程中了解了互斥锁,没想到在这里使用。感谢您的提示
  • 在父进程中打开后调用file.truncate()

标签: python subprocess stdout tee


【解决方案1】:

感谢Bamar 的建议:第一个和第二个 open() 都使用 'a' 有效。如果您需要对已存在的文件执行此操作,您可以使用 file.truncate() 在追加文件之前清空文件。

【讨论】:

  • 如果文件以'a' 模式打开,则不能保证所有系统上的所有写入都在末尾。不能保证 larges write()s 是原子的(多个进程的输出可能交错)。
【解决方案2】:

'w' 模式打开文件会截断文件 (as documented)。以'a' 模式打开文件可能适用于一些 系统。 POSIX says for O_APPEND flag:

如果设置,文件偏移量应设置为每次写入之前的文件末尾。

write()s that are larger than PIPE_BUF may interleave:

POSIX.1-2008 没有说明超过 {PIPE_BUF} 字节的写入请求是否是原子的,但要求 {PIPE_BUF} 或更少字节的写入应该是原子的。


问:我应该使用什么替代解决方案同时从父进程和子进程写入文件,而不会出现乱序或重叠的行?

使用行缓冲模式 (1) 打开文件,以在每行末尾刷新内部缓冲区——它应该保留行的大致相对顺序。如果行小于PIPE_BUF(在我的系统上为 4096 字节),那么它们不应“重叠”。


子进程可以将数据写入其标准输出,而您的父 Python 进程可以按照您喜欢的任何顺序将其写入文件。见how teed_call() function is implemented

【讨论】:

  • 我不介意投反对票,但我希望能有一个解释,让答案变得更好。
  • 我讨厌人们投了反对票而没有说明他们为什么这样做
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-24
  • 2021-09-23
  • 2012-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多