试图请求文件输入并将其保存在特定位置

2024-04-26 05:34:24 发布

您现在位置:Python中文网/ 问答频道 /正文

因此,我试图编写一个方法,保存用户选择的图片,并将图片添加到父类“activity”中。以下是我尝试过的:

    # Creating object from filedialog
    picture = filedialog.asksaveasfile(mode='r', title='Select activity picture', defaultextension=".jpg")
    
    # Check if cancelled
    if picture is None:
        return
    else:
        folder_dir = 'main/data/activity_pics'
        pic_name = 'rocket_league' #change to desc_to_img_name() later
        path = os.path.join(folder_dir, f'{pic_name}')
        
        # Making the folder if it does not exist yet
        if not os.path.exists(folder_dir):
            os.makedirs(folder_dir)
            
        # Creating a location object
        f = open(path, "a")
        
        # Writing picture on location object
        f.write(picture)
        
        # Closing
        f.close()

        # Check if successful
        if os.path.exists(path):
            print(f'File saved as {pic_name} in directory {folder_dir}')
            self.picture_path = path

稍后,我使用rocketleague.add_picture()调用该方法,其中我将rocketleague定义为Activity

我在网上找到了几种不同的解决方案,但似乎都不管用。当前,此脚本给出一个错误:

C:\Users\timda\PycharmProjects\group-31\venv\Scripts\python.exe C:/Users/timda/PycharmProjects/group-31/project/activities/random_activity_generator.py
Traceback (most recent call last):
  File "C:/Users/timda/PycharmProjects/group-31/project/activities/random_activity_generator.py", line 160, in <module>
    rocketleague.add_picture()
  File "C:/Users/timda/PycharmProjects/group-31/project/activities/random_activity_generator.py", line 46, in add_picture
    f.write(picture)
TypeError: write() argument must be str, not _io.TextIOWrapper

所以我猜我的open.write()只适用于字符串。我不确定我目前的方法是否有效

最方便的方法是什么


Tags: path方法nameifobjectosdirgroup
1条回答
网友
1楼 · 发布于 2024-04-26 05:34:24

根据您所描述的,您正在使用完全不同的方法来完成任务

我将首先解释您正在尝试做什么以及为什么它不起作用

->;因此,在您要求用户选择一个文件并创建了folder_dirpath之后,您希望将所选图片移动/复制到变量path描述的位置

问题,

  • 根据您的需要,您可能就在这里,但我觉得您应该使用filedialog.askopenfile()而不是filedialog.asksaveasfile(),因为您可能希望他们选择一个文件,而不是选择要将文件移动到的文件夹-您似乎已经有了目标folder_dir。但这又取决于你的需要
  • 重要的一点。在您的代码中,其中一条注释是:“创建位置对象”,而您使用了f = open(path, "a"),您没有在那里创建位置对象f只是一个以文本追加模式打开的file对象,如open()函数调用中第二个参数中的"a"所示。无法将二进制图像文件写入文本文件。这就是为什么错误消息会说,它希望将字符串写入文本文件,而不是二进制I/O包装器

解决方案

非常简单,使用实际方法移动文件以执行任务

因此,一旦您有了图像文件的地址(由用户在filedialog中选择-如上所述)-请注意,正如@Bryan所指出的,picture变量将始终是用户选择的文件的file handler。我们可以使用file handler的属性.name获取所选文件的绝对地址

>>> import tkinter.filedialog as fd
>>> a = fd.askopenfile()
# I selected a test.txt file

>>> a
<_io.TextIOWrapper name='C:/BeingProfessional/projects/Py/test.txt' mode='r' encoding='cp1252'>

# the type is neither a file, not an address.
>>> type(a)
<class '_io.TextIOWrapper'>
>>> import os

# getting the absolute address with name attribute
>>> print(a.name)
C:/BeingProfessional/projects/Py/test.txt
# check aith os.path
>>> os.path.exists(a.name)
True

注:
我们还可以使用filedialog.askopenfilename(),它只返回所选文件的地址,这样您就不必担心文件处理程序及其属性

我们已经有了目标folder_dir和一个新的文件名。 这就是我们所需要的,一个来源和目的地。 下面是复制文件的方法

这三种方法的作用相同。根据需要使用其中任何一个

import os
import shutil

os.rename("path/to/current/file.foo", "path/to/new/destination/for/file.foo")
shutil.move("path/to/current/file.foo", "path/to/new/destination/for/file.foo")
os.replace("path/to/current/file.foo", "path/to/new/destination/for/file.foo")

请注意,必须在源参数和目标参数中都包含文件名(file.foo)。如果文件被更改,则该文件将被重命名和移动

还要注意,在前两种情况下,创建新文件的目录必须已经存在。在Windows计算机上,具有该名称的文件必须不存在,否则将引发exception,但os.replace()将以静默方式替换文件,即使在该情况下也是如此

你的代码被修改了

# Creating object from filedialog
picture = filedialog.askopenfile(mode='r', title='Select activity picture', defaultextension=".jpg")

# Check if cancelled
if picture is None:
    return
else:
    folder_dir = 'main/data/activity_pics'
    pic_name = 'rocket_league' #change to desc_to_img_name() later
    path = os.path.join(folder_dir, f'{pic_name}')
    
    # Making the folder if it does not exist yet
    if not os.path.exists(folder_dir):
        os.makedirs(folder_dir)
        
   # the change here
   shutil.move(picture.name, path)  # using attribute to get abs address

    # Check if successful
    if os.path.exists(path):
        print(f'File saved as {pic_name} in directory {folder_dir}')
        self.picture_path = path

这个代码块的缩进不是很好,因为原始的问题格式没有缩进那么好

感谢布莱恩指出错误:)

相关问题 更多 >