你可以使用shutil.copy()和os.rename()在Python中覆盖不同文件夹中的文件。

huangapple go评论61阅读模式
英文:

How can I overwrite a file in a different folder using shutil.copy() and os.rename() in Python?

问题

我有一个脚本,它输出一个包含各种数据的 Excel 文件 '.xlsx'。它在一个文件夹中生成一个带有日期名称的文件,然后使用 shutil.copy() 生成一个副本到另一个文件夹。然后我使用 os.rename() 重命名文件,但是不是覆盖已经存在的文件,而是产生以下错误:

"FileExistsError: [WinError 183] 当文件已经存在时无法创建文件:"

我需要每次运行脚本时文件的名称都完全相同,因为它随后用作 PowerBI 的自动输入文件。

当前代码如下:

# 选择要复制的文件和复制到的位置
src_file = vb.output_path
destination = vb.path_reports_cashflowcopy

# 复制文件
shutil.copy(src_file, destination)

# 定义复制路径
cashflow_copy_path = vb.ROOT_DIR + '\\Data_and_Reports\\Reports\\Cashflow Copies\\'

# 重命名文件
os.rename(cashflow_copy_path + str(date.today()) + ' -  Lettings Report BETA - '  +       vb.academic_year_selection +  '.xlsx',
          cashflow_copy_path + 'Copy ' + vb.academic_year_selection + '.xlsx')

src_file 是原始生成的 Excel 文件。
vb.xxxxxx 是来自连接的脚本,描述了各种文件路径和其他用于命名文件的输入。

英文:

I have a script which outputs an excel file '.xlsx' containing various data. It generates a file with the date in the name in one folder, and then generates a copy, using shutil.copy(), in a separate folder. I then rename the file using os.rename(), however instead of overwriting the file already there, it produces the following error:

"FileExistsError: [WinError 183] Cannot create a file when that file already exists:"

I need the file to be exactly the same name everytime the script is run, as it is subsequently used as an automatic input file for PowerBI.

Current code is as follows:

# Select file you want to copy & where to copy it to
src_file = vb.output_path
destination = vb.path_reports_cashflowcopy

# Copy the file
shutil.copy(src_file, destination)

# Define copy path
cashflow_copy_path = vb.ROOT_DIR + '\\Data_and_Reports\\Reports\\Cashflow Copies\\'

# Rename the file
os.rename(cashflow_copy_path + str(date.today()) + ' -  Lettings Report BETA - '  +       vb.academic_year_selection +  '.xlsx',
          cashflow_copy_path + 'Copy ' + vb.academic_year_selection + '.xlsx')

src_file is the original output excel file created.
vb.xxxxxx is from a connected script which describes various file paths and other inputs used to name the files.

答案1

得分: 1

为了避免在重命名文件时出现“FileExistsError”,您可以在重命名之前检查目标文件是否已存在。

import os
import shutil
from datetime import date

# 选择要复制的文件以及复制到的目标位置
src_file = vb.output_path
destination = vb.path_reports_cashflowcopy

# 复制文件
shutil.copy(src_file, destination)

# 定义复制路径
cashflow_copy_path = vb.ROOT_DIR + '\\Data_and_Reports\\Reports\\Cashflow Copies\\'

# 重命名文件
new_file_name = cashflow_copy_path + 'Copy ' + vb.academic_year_selection + '.xlsx'
existing_file = cashflow_copy_path + str(date.today()) + ' -  Lettings Report BETA - ' + vb.academic_year_selection + '.xlsx'

if os.path.exists(existing_file):
    os.remove(existing_file)  # 如果存在,则删除现有文件

os.rename(src_file, new_file_name)
英文:

To avoid the "FileExistsError" when renaming the file, you can check if the destination file already exists before renaming it.

import os
import shutil
from datetime import date

# Select file you want to copy & where to copy it to
src_file = vb.output_path
destination = vb.path_reports_cashflowcopy

# Copy the file
shutil.copy(src_file, destination)

# Define copy path
cashflow_copy_path = vb.ROOT_DIR + '\\Data_and_Reports\\Reports\\Cashflow Copies\\'

# Rename the file
new_file_name = cashflow_copy_path + 'Copy ' + vb.academic_year_selection + '.xlsx'
existing_file = cashflow_copy_path + str(date.today()) + ' -  Lettings Report BETA - ' + vb.academic_year_selection + '.xlsx'

if os.path.exists(existing_file):
    os.remove(existing_file) # Delete the existing file if it exists

os.rename(src_file, new_file_name)

答案2

得分: 0

这是一些操作系统的预期行为,参见os.rename()文档,该文档也提供了解决方案(重点在于):

> 将文件或目录src重命名为dst。如果dst存在,该操作将在许多情况下失败,将引发OSError子类:
在Windows上,如果dst存在,将始终引发FileExistsError。如果src和dst位于不同的文件系统上,操作可能会失败。使用shutil.move()支持移动到不同的文件系统。
在Unix上,如果src是文件并且dst是目录,或者反之亦然,将分别引发IsADirectoryError或NotADirectoryError。如果两者都是目录且dst为空,则将替换dst而不发出警告。如果dst是非空目录,则会引发OSError。如果两者都是文件,则在用户具有权限的情况下将静默替换dst。如果src和dst位于不同的文件系统上,操作可能会在某些Unix版本上失败。如果成功,重命名将是原子操作(这是POSIX的要求)。
此函数可以支持指定src_dir_fd和/或dst_dir_fd以提供相对于目录描述符的路径。
如果要实现跨平台覆盖目标,请使用replace()

因此,切换到os.replace应该会奏效。

摘自关于os.replace的相关部分

> 将文件或目录src重命名为dst。如果dst是非空目录,将引发OSError。如果dst存在且为文件,则在用户具有权限的情况下将静默替换。如果src和dst位于不同的文件系统上,操作可能会失败。

英文:

This is expected behaviour on some OS, see the docs on os.rename which also give a solution (emphasis mine):

> Rename the file or directory src to dst. If dst exists, the operation will fail with an OSError subclass in a number of cases:
On Windows, if dst exists a FileExistsError is always raised. The operation may fail if src and dst are on different filesystems. Use shutil.move() to support moves to a different filesystem.
On Unix, if src is a file and dst is a directory or vice-versa, an IsADirectoryError or a NotADirectoryError will be raised respectively. If both are directories and dst is empty, dst will be silently replaced. If dst is a non-empty directory, an OSError is raised. If both are files, dst will be replaced silently if the user has permission. The operation may fail on some Unix flavors if src and dst are on different filesystems. If successful, the renaming will be an atomic operation (this is a POSIX requirement).
This function can support specifying src_dir_fd and/or dst_dir_fd to supply paths relative to directory descriptors.
If you want cross-platform overwriting of the destination, use replace().

So switching to os.replace should do the trick

Extract from the relevant section on os.replace:

> Rename the file or directory src to dst. If dst is a non-empty directory, OSError will be raised. If dst exists and is a file, it will be replaced silently if the user has permission. The operation may fail if src and dst are on different filesystems.

huangapple
  • 本文由 发表于 2023年6月1日 19:42:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/76381509.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定