Python os.path.join访问阻止重命名操作的文件

Python os.path.join访问阻止重命名操作的文件,python,io,path,Python,Io,Path,我试图通过在解码失败时备份格式错误的文件来处理JSON解码,但我遇到了一些奇怪的行为,这是我在os.path.join方法中没有预料到的 以下代码因异常而失败:PermissionError:[WinError 32]进程无法访问该文件,因为另一个进程正在使用它:“file.txt”->“file.txt\\.bak” file_path = "file.txt" try: with open(file_path, 'r') as f: json.load(f) ex

我试图通过在解码失败时备份格式错误的文件来处理JSON解码,但我遇到了一些奇怪的行为,这是我在
os.path.join
方法中没有预料到的

以下代码因异常而失败:
PermissionError:[WinError 32]进程无法访问该文件,因为另一个进程正在使用它:“file.txt”->“file.txt\\.bak”

file_path = "file.txt"

try:
    with open(file_path, 'r') as f:
        json.load(f)

except json.JSONDecodeError as e:
    os.rename(file_path, os.path.join(file_path, '.bak'))
如果我这样更改参数:
os.rename(file_path,file_path+'.bak')
代码按预期执行,没有权限错误。似乎
os.path.join
方法实际上访问文件,而不是严格的字符串操作。这是预期的行为吗?

os.path.join(file_path,.bak'))
实际上会像您在错误代码中看到的那样为您提供
file.txt\\.bak
,但是
file_path+'.bak'
会为您提供正确的文件名
file.txt.bak

在它的参数之间附加一个分隔符,因此它最终也会在您的案例中添加该分隔符

例如在MacOS中,您可以看到它在每个参数之间添加了分隔符。join在附加目录名时更为有用,即使用目录路径附加完整文件名的目录名

In [4]: import os                                                                                                                                                                 

In [5]: os.path.join('filename','.bak')                                                                                                                                           
Out[5]: 'filename/.bak'

In [6]: os.path.join('folder1', 'folder2')                                                                                                                                        
Out[6]: 'folder1/folder2'
由于Windows操作系统试图在名为
file.txt
的文件夹中创建一个文件
.bak
,这是不可能的,因为file.txt是一个普通文件,而不是一个正确的目录

使用
file_path+'.bak
在您想要的文件夹中正确创建
file.path.bak
,因此您不会在那里看到错误

os.path.join(file_path,'.bak'))
实际上会像您在错误代码中看到的那样为您提供
file.txt\\.bak
,但是
file_path+'.bak'
会为您提供正确的文件名
file.txt.bak

在它的参数之间附加一个分隔符,因此它最终也会在您的案例中添加该分隔符

例如在MacOS中,您可以看到它在每个参数之间添加了分隔符。join在附加目录名时更为有用,即使用目录路径附加完整文件名的目录名

In [4]: import os                                                                                                                                                                 

In [5]: os.path.join('filename','.bak')                                                                                                                                           
Out[5]: 'filename/.bak'

In [6]: os.path.join('folder1', 'folder2')                                                                                                                                        
Out[6]: 'folder1/folder2'
由于Windows操作系统试图在名为
file.txt
的文件夹中创建一个文件
.bak
,这是不可能的,因为file.txt是一个普通文件,而不是一个正确的目录


使用
file_path+'.bak
在您想要的文件夹中正确创建
file.path.bak
,因此您不会在那里看到错误

错误消息是关键。通常在Windows上,原因(因为另一个进程正在使用)是错误的,但名称('file.txt'->'file.txt\.bak')是正确的

Join不是字符串连接,但要求除最后一个路径成员外的所有路径成员都表示文件夹。因此,您正在尝试在名为
file.txt
文件夹中创建一个文件
.bak
。这是不可能的,因为
file.txt
是普通文件而不是目录

另一方面,当您使用
os.rename(file_path,file_path+'.bak')
时,您将
file.txt
重命名为基础文件系统允许的同一文件夹中的
file.txt.bak
,因此没有错误

因此,除了错误消息的开头,行为与预期完全一致



由于我不是微软的核心开发人员,下面是一个大胆的猜测。系统给出的错误数量是有限的。rename C函数接收到2个字符串,并将其传递给系统调用进行重命名。正如预期的那样,文件系统生成了一个错误,但由于它既不是物理错误,也不是文件系统完全错误,所以它只是选择了一个权限拒绝原因。这并不是真的错,因为不允许在普通文件下创建文件夹。但不幸的是,该错误的消息被另一个愚蠢的进程使用了

错误消息是关键。通常在Windows上,原因(因为另一个进程正在使用)是错误的,但名称('file.txt'->'file.txt\.bak')是正确的

Join不是字符串连接,但要求除最后一个路径成员外的所有路径成员都表示文件夹。因此,您正在尝试在名为
file.txt
文件夹中创建一个文件
.bak
。这是不可能的,因为
file.txt
是普通文件而不是目录

另一方面,当您使用
os.rename(file_path,file_path+'.bak')
时,您将
file.txt
重命名为基础文件系统允许的同一文件夹中的
file.txt.bak
,因此没有错误

因此,除了错误消息的开头,行为与预期完全一致



由于我不是微软的核心开发人员,下面是一个大胆的猜测。系统给出的错误数量是有限的。rename C函数接收到2个字符串,并将其传递给系统调用进行重命名。正如预期的那样,文件系统生成了一个错误,但由于它既不是物理错误,也不是文件系统完全错误,所以它只是选择了一个权限拒绝原因。这并不是真的错,因为不允许在普通文件下创建文件夹。但不幸的是,这个错误的消息是,它被另一个愚蠢的进程使用了

我忘记了分隔符,这是一个很好的捕获。这是否解释了为什么会产生权限错误?这是因为我们没有一个名为
file.txt
的文件夹,您试图在其中创建
bak
文件@Alex,我已经更新了我的答案,原因如下:)我想是有道理的,错误消息有点误导Cool@Alex我也更新了我的答案,原因如下:)我忘记了分隔符,这是一个很好的发现。这是否解释了为什么会产生权限错误?这是因为我们没有名为
file的文件夹。