尝试使用python删除文件,但出现WinError 32权限错误

时间:2019-03-21 19:13:51

标签: python python-3.x pygame

所以我有一个非常奇怪的问题,确实很难复制。根据文件类型,我正在使用几个不同的库播放声音。我希望能够删除声音,因此在使用os.remove()删除文件之前,我先清除音频播放器(通过重新分配audio_player变量),那是当我收到权限错误时,但仅当我清除了音频播放器时使用pygame。我不知道为什么会发生这种情况,但是我已经能够始终如一地将其复制到一个测试文件中,这既是该文件又是原始文件。它与SoundPlayer.reload_sound_from_different_file()

原始aka AudioPlayer

import pygame
import MetaData
import os
import time
from random import random
from PyQt5.QtCore import pyqtSignal, QObject, QRunnable, pyqtSlot


class PlaysoundException(Exception):
    pass


class SoundSigs(QObject):
    time_changed = pyqtSignal()
    set_current_time = pyqtSignal(float)
    reset_cursor = pyqtSignal()
    error = pyqtSignal(str)


class SoundPlayer(QRunnable):
    def __init__(self):
        super(SoundPlayer, self).__init__()
        self.path = ''
        self.signals = SoundSigs()
        self.wav_list = ['.wav']
        self.pygame_list = ['.flac', '.ogg', '.mp3']
        self.current_result = ''
        self.pixel_time_conversion_rate = 0
        self.audio_player = AudioPlayer()

    def reset(self):
        self.audio_player.stop()
        self.audio_player = AudioPlayerPlaceholder()

    def space_bar(self):
        if self.audio_player.ended:
            self.audio_player.goto(0)
        elif self.audio_player.playing:
            self.audio_player.pause()
        else:
            self.audio_player.resume()

    @pyqtSlot()
    def run(self):
        while True:
            while self.audio_player.playing and not self.audio_player.ended and not \
                    self.audio_player.passed_download_head:
                time.sleep(.003)
                self.signals.time_changed.emit()
            time.sleep(.01)

    def load(self, path, pixel_time_conversion_rate):
        self.pixel_time_conversion_rate = pixel_time_conversion_rate
        self.audio_player = self.get_correct_audio_player(path)
        self.audio_player.load(path)

    def get_correct_audio_player(self, path):
        file_type = os.path.splitext(path)[1].lower()
        if file_type in self.wav_list:
            return WavPlayer()
        elif file_type in self.pygame_list:
            return PygamePlayer()

    def load_segment(self, path, true_duration, pixel_time_conversion_rate):
        current_time = self.audio_player.current_time
        playing = self.audio_player.playing
        self.audio_player.stop()
        self.audio_player = self.get_correct_audio_player(path)
        self.pixel_time_conversion_rate = pixel_time_conversion_rate
        self.audio_player.load_segment(path, true_duration)
        self.audio_player.goto(current_time)
        if playing:
            self.audio_player.play()

    def preload(self, true_duration, pixel_time_conversion_rate):
        self.audio_player.stop()
        self.signals.time_changed.emit()
        self.audio_player = AudioPlayerPlaceholder()
        self.pixel_time_conversion_rate = pixel_time_conversion_rate
        self.audio_player.preload(true_duration)
        self.audio_player.play()

    def reload_sound_from_different_file(self, path):
        current_time = self.audio_player.current_time
        playing = self.audio_player.playing
        self.audio_player.stop()
        self.audio_player = self.get_correct_audio_player(path)
        self.audio_player.load(path)
        self.audio_player.goto(current_time)
        if playing:
            self.audio_player.play()

    @staticmethod
    def calculate_px_time_conversion_rate(waveform_width, sound_duration):
        return waveform_width/sound_duration

    def goto(self, position):
        self.audio_player.goto(position/self.pixel_time_conversion_rate)
        self.signals.time_changed.emit()


class AudioPlayerSigs(QObject):
    error = pyqtSignal(str)


class AudioPlayer:
    def __init__(self):
        self.signals = AudioPlayerSigs()
        self.loaded = False
        self._playing = False
        self.loop = False
        self.segment = False
        self._path = ''
        self.path = ''
        self._original_path = ''
        self._meta_data = None
        self._duration = 0
        self.attempted_current_time = 0
        self.passed_download_head = False
        self._current_time_start = 0
        self.current_time_stop = 0
        self._current_time_stop = 0
        self._current_time = 0
        self.current_time = 0

    def __del__(self):
        self._meta_data = None

    @property
    def current_time_stop(self):
        if not self.playing:
            return self._current_time_stop
        return time.time()

    @current_time_stop.setter
    def current_time_stop(self, value):
        self._current_time_stop = value

    @property
    def playing(self):
        return self._playing

    @playing.setter
    def playing(self, value):
        if value:
            self._current_time_start = time.time()
        else:
            self._current_time = self.current_time
            self.current_time_stop = time.time()
            self._current_time_start = time.time()
        self._playing = value

    @property
    def path(self):
        return self._path

    @path.setter
    def path(self, value):
        self._original_path = value
        self._path = get_short_path_name(value)

    @property
    def current_time(self) -> int:
        if self.playing:
            return int((self.current_time_stop - self._current_time_start)*1000) + self._current_time
        return self._current_time

    @current_time.setter
    def current_time(self, value):
        self._current_time_start = time.time()
        self._current_time = value

    @property
    def meta_data(self):
        if self.loaded:
            return self._meta_data
        self._meta_data = self.get_meta_file()
        return self._meta_data

    @property
    def true_duration(self):
        return self.meta_data['duration']

    @property
    def duration(self):
        if self.segment:
            return self._duration
        return self.true_duration

    @property
    def ended(self):
        return self.duration <= self.current_time

    def get_meta_file(self):
        return MetaData.get_meta_file(self._original_path)

    def load(self, path):
        self.path = path

        self._meta_data = self.get_meta_file()
        self.loaded = True
        self._load(self.path)

    def _load(self, path):
        pass

    def reload(self, path, playing):
        self.path = path
        self._meta_data = self.get_meta_file()
        self.stop()
        self._reload(path)
        self.loaded = True
        if playing:
            self.play()

    def _reload(self, path):
        pass

    def play(self):
        if not self.playing:
            self.playing = True
            self._play()

    def _play(self):
        pass

    def pause(self):
        if self.playing:
            self.playing = False
            self._pause()

    def _pause(self):
        pass

    def resume(self):
        if not self.playing:
            self.playing = True
            self._resume()

    def _resume(self):
        pass

    def stop(self):
        if self.loaded:
            self._reset()
            self._stop()

    def _stop(self):
        pass

    def goto(self, position):
        self.current_time = position
        if self.segment and position >= self.true_duration:
            self.pause()
            self.attempted_current_time = position
            self.passed_download_head = True
        else:
            self._goto(position)
        if not self.playing:
            self._pause()

    def _goto(self, position):
        pass

    def _reset(self):
        self.loaded = False
        self.playing = False
        self.loop = False
        self.segment = False
        self.passed_download_head = False
        self.current_time = 0

    def end(self):
        if self.loop:
            self.goto(0)
            self.play()

    def swap_file_with_complete_file(self, path):
        if self.passed_download_head:
            current_time = self.attempted_current_time
        else:
            current_time = self.current_time
        playing = self.playing
        self.stop()
        self.reload(path, playing)
        self.goto(current_time)

    load_rest_of_segment = swap_file_with_complete_file

    def swap_file_with_incomplete_file(self, path, duration):
        current_time = self.current_time
        self.stop()
        self.load_segment(path, duration)
        self.goto(current_time)
        self.play()

    def load_segment(self, path, duration):
        self.segment = True
        self._duration = duration
        self.load(path)


class WavPlayer(AudioPlayer):
    def __init__(self):
        super(WavPlayer, self).__init__()
        self.alias = ''

    def __del__(self):
        self.win_command('close', self.alias)

    def _load(self, path):
        self.alias = 'playsound_' + str(random())
        self.win_command('open "' + self.path + '" alias', self.alias)
        self.win_command('set', self.alias, 'time format milliseconds')

    def _reload(self, path):
        self._load(path)

    def _play(self):
        self.win_command('play', self.alias, 'from', str(round(self.current_time)), 'to', str(self.duration))

    def _pause(self):
        self.win_command('pause', self.alias)

    def _resume(self):
        self.win_command('play', self.alias)

    def _stop(self):
        self.win_command('stop', self.alias)

    def _goto(self, position):
        self.win_command('play', self.alias, 'from', str(round(position)), 'to', str(self.duration))

    @staticmethod
    def win_command(*command):
        from ctypes import c_buffer, windll
        from sys import getfilesystemencoding
        buf = c_buffer(255)
        command = ' '.join(command).encode(getfilesystemencoding())
        errorCode = int(windll.winmm.mciSendStringA(command, buf, 254, 0))
        if errorCode:
            errorBuffer = c_buffer(255)
            windll.winmm.mciGetErrorStringA(errorCode, errorBuffer, 254)
            exceptionMessage = ('\n    Error ' + str(errorCode) + ' for command:'
                                                                  '\n        ' + command.decode() +
                                '\n    ' + errorBuffer.value.decode())
            raise PlaysoundException(exceptionMessage)
        return buf.value


class PygamePlayer(AudioPlayer):
    def __init__(self):
        super(PygamePlayer, self).__init__()
        pygame.mixer.pre_init(48000, -16, 2, 1024)

    def __del__(self):
        pygame.mixer.quit()
        self.path = None
        print('deleted')

    def _load(self, path):
        frequency = int(self.meta_data['sample rate'])
        channels = int(self.meta_data['channels'])
        pygame.mixer.quit()
        pygame.mixer.init(frequency=frequency, channels=channels)
        try:
            pygame.mixer.music.load(path)
        except pygame.error:
            self.signals.error.emit("Couldn't play this file!  It may be that it's corrupted.  "
                                    "Try downloading it again.")

    def _reload(self, path):
        try:
            pygame.mixer.music.load(self.path)
        except pygame.error:
            self.signals.error.emit("Couldn't play this file!  It may be that it's corrupted.  "
                                    "Try downloading it again.")

    def _play(self):
        try:
            pygame.mixer.music.play()
        except Exception as e:
            self.signals.error.emit(e)

    def _pause(self):
        pygame.mixer.music.pause()

    def _resume(self):
        pygame.mixer.music.unpause()

    def _stop(self):
        pygame.mixer.music.stop()

    def _goto(self, position):
        try:
            self._reload(self.path)
            pygame.mixer.music.play(start=round(position)/1000)
        except pygame.error:
            pygame.mixer.music.set_pos(position)


class AudioPlayerPlaceholder(AudioPlayer):
    def __init__(self):
        super(AudioPlayerPlaceholder, self).__init__()
        self.passed_download_head = True

    @property
    def current_time(self):
        return self._current_time

    @current_time.setter
    def current_time(self, value):
        self._current_time = value

    @property
    def ended(self):
        return False

    def goto(self, position):
        self.current_time = position

    def preload(self, duration):
        self._duration = duration
        self.current_time = 0


def get_short_path_name(long_name):
    from ctypes import wintypes
    import ctypes
    _GetShortPathNameW = ctypes.windll.kernel32.GetShortPathNameW
    _GetShortPathNameW.argtypes = [wintypes.LPCWSTR, wintypes.LPWSTR, wintypes.DWORD]
    _GetShortPathNameW.restype = wintypes.DWORD
    """
    Gets the short path name of a given long path.
    http://stackoverflow.com/a/23598461/200291
    """
    output_buf_size = 0
    while True:
        output_buf = ctypes.create_unicode_buffer(output_buf_size)
        needed = _GetShortPathNameW(long_name, output_buf, output_buf_size)
        if output_buf_size >= needed:
            return output_buf.value
        else:
            output_buf_size = needed

测试文件

from AudioPlayer import SoundPlayer
import time
import os

file_name = "<file path>"
player = SoundPlayer()
player.load(file_name, 1)
player.audio_player.play()
time.sleep(5)
player.reload_sound_from_different_file(file_name)
time.sleep(2)
player.audio_player.stop()
player.reset()
time.sleep(1)
os.remove(file_name)

我知道这个问题要问很多,但是我已经坚持了3天,哈哈。任何帮助将不胜感激!

3 个答案:

答案 0 :(得分:0)

几周前,我在工作中的应用程序上遇到Windows安全性类似的问题。最终为我解决的是从命令提示符设置为管理员的批处理文件中调用脚本。如果要尝试,请使用以下命令创建一个.bat文件:

cd path/to/your/script
python myscript.py

然后创建一个批处理文件的快捷方式,并在properties标签中,依次选择advancedrun as administrator。每当双击文件并以我自己的方式克服这些权限错误时,它将以管理员身份运行所有脚本。它也可能对您有用。

答案 1 :(得分:0)

以某种方式,您安装的软件包可能不会被标记为受信任的应用程序,这是除尝试通过右键单击应用程序管理员并单击以管理员身份运行来临时授予应用程序管理员访问权限之外,尝试做的其他事情。

要取消阻止程序包,请导航至/python/lib/,然后查找您已安装的程序包(如果有)或程序中所述的程序包。右键单击所有python文件,根据情况,它可能会显示一个框,显示“取消阻止该程序”。如果是,请选中该框并单击“应用”,然后单击“确定”。我建议对您正在使用的软件包中的每个文件执行此操作。

如果这行不通(这很有可能不行,因为这是一个不寻常的错误),请告诉我。

答案 2 :(得分:0)

好的,我知道了!问题是,当您多次退出混音器时,pygame确实不喜欢它。每次初始化新播放器时,我都会退出,由于某种原因,第二次播放器无法完全释放文件。我最终要做的是先将文件加载到内存中,然后以这种方式将其提供给pygame,然后我可以在闲暇时删除它:)