Как я могу предотвратить ошибку PermissionError при попытке удалить .GIF, ранее «запущенный» в QLabel PySide6?Python

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Как я могу предотвратить ошибку PermissionError при попытке удалить .GIF, ранее «запущенный» в QLabel PySide6?

Сообщение Anonymous »

Я был бы очень признателен за вашу помощь в решении этой проблемы PermissionError, когда я пытаюсь удалить файл .GIF, который я ранее «воспроизводил» в своем приложении PySide6. Полный воспроизводимый код + пример файла .gif ниже.
В моем приложении PySide6 я создаю QLabel и отображаю внутри него файл .GIF.
Это предполагает сначала создание объекта QMovie (который принимает относительный путь к файлу .GIF из текущего каталога), а затем использование метода QLabel.setMovie(QMovie) для отображения файл .GIF внутри этикетки. Наконец, метод QMovie.start() запускает воспроизведение .GIF.
После этого я хочу иметь возможность удалить файл .GIF. Я читал о двух функциях Python для удаления файлов: os.remove() и pathlib.Path.unlink() .
Обе эти функции работают как желательно при отсутствии кода PySide6. Я могу удалить файл .GIF со своего компьютера без каких-либо ошибок PermissionError.
Ошибка PermissionError появляется, когда я пытаюсь вызвать любую из этих функций после вызова QMovie .start() для «воспроизведения» моего файла .GIF внутри моего приложения PySide6. Вот полный оператор PermissionError:

Код: Выделить всё

PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'test_gif_question_mark.gif'
Я использовал psutil, чтобы прочитать все процессы на моей машине, и он сообщает мне, что процесс python. exe «использует» мой файл .GIF, и никакие другие процессы его не используют.
Ошибка PermissionError не появляется, если я не вызываю QMovie.start() т.е. я могу удалить файл .GIF после создания объекта QMovie и даже после вызова QLabel.setMovie(QMovie) .
Очевидно, что мое приложение PySide6 открывает и считывает данные из файла .GIF, чтобы отобразить и «воспроизвести» связанную с ним анимацию. Что для меня неочевидно, так это то, как «закрыть» файл .GIF, чтобы процесс python.exe прекратил «использовать» файл .GIF, давая мне возможность удалить его.
Вот набор действий, которые я пытался «закрыть» файл .GIF:
  • Вызов QMovie.stop() .
  • Вызов QLabel.clear() .
  • Удаление объекта QMovie с помощью del.
  • Удаление QLabel объект с del .
  • Закрытие QApplication .

    Удаление QApplication с помощью del .
  • Удаление Экземпляр QMainWindow с использованием del — это единственный экземпляр в моих переменных после всего вышеперечисленного.
Ни один из приведенных выше подходов не предотвращает ошибку PermissionError, если я впоследствии попытаюсь удалить файл .GIF с помощью os.remove() или Path.unlink() . Используя psutil , я вижу, что даже после всех этих подходов python.exe все еще «использует» мой файл .GIF.
Мне кажется например, QMovie.stop() не делает то, что я хочу - я хочу, чтобы он «отпустил» и «закрыл» файл .GIF, чтобы процесс python.exe был больше не использую его, и я могу попросить Windows удалить файл.
Если вы знаете, как я могу заставить python.exe прекратить использование файла .GIF или любые другие решения, буду очень благодарен за вашу помощь.
Полный воспроизводимый код:

Код: Выделить всё

import sys
import os
from pathlib import Path
from PySide6.QtWidgets import QMainWindow, QVBoxLayout, QWidget, QApplication, QPushButton, QLabel, QHBoxLayout
from PySide6.QtGui import QMovie

# Description: This script builds a small QApplication GUI with buttons that stimulate various steps in the process
# of using, displaying, stopping using, and finally trying to delete a .gif file.

class MainWindow(QMainWindow):
def __init__(self):
super().__init__()

# Specify the path to the gif file from the current directory:
self.path_to_gif = 'test_gif_question_mark.gif'

# Create an instance of the QLabel class:
self.my_label = QLabel()

# Placeholder for the QMovie object:
self.my_QMovie = None

# Create a button to make the QMovie object:
my_button_create_qmovie = QPushButton()
my_button_create_qmovie.setText('Create QMovie')
my_button_create_qmovie.clicked.connect(self.clicked_create_button)

# Create a button to display the QMovie object in the QLabel:
my_button_display_qmovie = QPushButton()
my_button_display_qmovie.setText('Display QMovie')
my_button_display_qmovie.clicked.connect(self.clicked_display_button)

# Create a button to try to stop using the gif:
my_button_stop_using_gif = QPushButton()
my_button_stop_using_gif.setText('Try to stop using gif file')
my_button_stop_using_gif.clicked.connect(self.clicked_stop_button)

# Create a button to try to delete the gif:
my_button_delete_gif = QPushButton()
my_button_delete_gif.setText('Delete gif file')
my_button_delete_gif.clicked.connect(self.clicked_delete_button)

# Place the buttons in a horizontal layout:
layout_h_1 = QHBoxLayout()
layout_h_1.addWidget(my_button_create_qmovie)
layout_h_1.addWidget(my_button_display_qmovie)
layout_h_2 = QHBoxLayout()
layout_h_2.addWidget(my_button_stop_using_gif)
layout_h_2.addWidget(my_button_delete_gif)

# Assign the horizontal layouts to empty widgets:
widget_h_1 = QWidget()
widget_h_1.setLayout(layout_h_1)
widget_h_2 = QWidget()
widget_h_2.setLayout(layout_h_2)

# Place the label &  buttons in a vertical layout:
layout_v = QVBoxLayout()
layout_v.addWidget(self.my_label)
layout_v.addWidget(widget_h_1)
layout_v.addWidget(widget_h_2)

# Create a placeholder widget to hold the layout.
widget = QWidget()
widget.setLayout(layout_v)

# Set the central widget of the main window:
self.setCentralWidget(widget)

def clicked_create_button(self):
# Create a QMovie to display:
self.my_QMovie = QMovie(self.path_to_gif)
print('\nCreated QMovie object using path to .gif file')

def clicked_display_button(self):
# Display the gif inside the label:
self.my_label.setMovie(self.my_QMovie)
# Start the movie playing:
self.my_QMovie.start()
print('\nDisplayed and started QMovie')

def clicked_delete_button(self):
# Use os.remove to try to delete the gif file:
# os.remove(self.path_to_gif)

# Use pathlib.unlink to try to delete the gif file:
path_gif = Path(self.path_to_gif)
path_gif.unlink()

def clicked_stop_button(self):
# Try different things to get python to stop using the .gif file:
# Try 'stopping' the QMovie object:
self.my_QMovie.stop()

# Try clearing the QLabel:
self.my_label.clear()

# Try deleting the QMovie object:
del self.my_QMovie

# Try deleting the QLabel:
del self.my_label

# Run the QApplication:
app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec()

print('app finished')

# Try deleting the QApplication after it has finished:
del app

# Try deleting the MainWindow:
del w

# Try deleting the gif file even after the QApplication has closed:
os.remove('test_gif_question_mark.gif')
.GIF-файл для тестирования:
test_gif_question_mark.gif

Подробнее здесь: https://stackoverflow.com/questions/786 ... ously-star
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»