Python 3 : subprocess. run ('mv' )使目标保持打开状态

标签 python python-3.x

我有一个脚本,它使用一个非常简单的基于文件的 IPC 来与另一个程序进行通信。我用新内容编写一个 tmp 文件,并将其 mv 到 IPC 文件上以保留内容原子(另一个程序监听重命名事件)。

但现在问题来了:这工作了 2 到 3 次,但随后交换被卡住了。

time.sleep(10)
# check lsof => target file not opened
subprocess.run(
    "mv /tmp/tempfile /tmp/target",
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
    universal_newlines=True,
    shell=True,
)
# check lsof => target file STILL open
time.sleep(10)

/tmp/tempfile 将为每次写入做好准备

第一次运行结果:

$ lsof /tmp/target
COMMAND  PID        USER   FD   TYPE DEVICE SIZE/OFF  NODE NAME
python  1714      <user>   3u   REG   0,18      302 10058 /tmp/target

让它保持打开状态,直到我终止主 python 程序。连续运行会按预期更改内容、inode 和文件描述符,但它仍然打开,这是我不希望从 mv 中得到的。

当上面这些行的 python 程序关闭时,文件最终被关闭。

编辑:

发现错误:错误处理 tempfile.mkstemp()。请参阅:https://docs.python.org/3/library/tempfile.html#tempfile.mkstemp

我像这样创建了临时文件:

_fd, temp_file_path = tempfile.mkstemp()

我丢弃了默认打开的文件描述符_fd。我没有关闭它,所以即使在移动之后它仍然保持打开状态。这导致了一个打开的目标,并且由于我只是在目标上进行 lsof,所以我没有看到临时文件已经打开。这将是更正后的版本:

fd, temp_file_path = tempfile.mkstemp()
fd.write(content)
fd.close()

# ... mv/rename via shell execution/shutil/pathlib

非常感谢大家的帮助和建议!

最佳答案

我无法重现此行为。我创建了一个文件/tmp/tempfile并使用 subprocess.run 运行 python 脚本给你打电话,然后是长长的 sleep 。 /tmp/target没有在使用中,我也没有在 lsof -p <pid> 中看到任何意外打开的文件.

(编辑)我对此并不感到惊讶,因为您的子进程命令无法打开文件:mv不打开其参数(您可以使用 ltrace 进行检查)和 subprocess.run除了将其传递为 exec 之外,不会解析其参数或对其进行任何操作-编辑。

但是,当我添加一些行来打开文件并写入文件,然后移动该文件时,我看到了与您描述的相同的行为。这是代码:

import subprocess
out=open('/tmp/tempfile', 'w')
out.write('hello')
subprocess.run(
    "mv /tmp/tempfile /tmp/target",
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
    universal_newlines=True,
    shell=True,
)
import time
time.sleep(5000)

在这种情况下,文件仍然打开,因为它从未关闭,即使已重命名,原始文件句柄仍然存在。我敢打赌,您的代码中有类似的内容正在创建此文件并为其保留打开的句柄。

关于Python 3 : subprocess. run ('mv' )使目标保持打开状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55496679/

相关文章:

python - 将 Qt Pyside2 与 asyncio await 语法一起使用?

python-3.x - pip install pyarrow 在 Linux/在 docker 中失败

python - 如何将 tensorflow 变量打印到小数点后两位?

Python Tkinter。数据点的最佳拟合椭圆

python - 如何在不输入密码的情况下运行 Fabric 任意 sudo 命令?

python - 如何使用变量设置 Discord 嵌入消息的图像?

Python按多个条件排序

python - 类型错误:+ 不支持的操作数类型: 'dict_keys' 和 'list'

python - 当有 2 个相同的字符时如何索引列表

python - 为什么 Datetime 和 Timedelta 之间的持续时间短了 1 小时?