[英]Trying to ask for a file input and save it in specific location
所以我正在嘗試編寫一種方法來保存用戶選擇的圖片並將圖片添加到父類“活動”中。 這是我嘗試過的:
# 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() 不是用於字符串以外的任何東西。 我不確定我目前的方法是否有效。
什么是最方便的方法來做到這一點?
根據您的描述,您正在使用完全不同的方法來執行任務。
我將首先解釋您正在嘗試做什么以及為什么它不起作用。
-> 因此,在您要求用戶選擇文件並創建folder_dir
和path
,您希望將所選圖片移動/復制到變量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
這個代碼塊的縮進不是很好,因為原始問題格式沒有縮進那么大。
感謝布萊恩指出錯誤:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.