添加记录器原因无法腌制_thread.RLock对象错误

时间:2018-08-25 16:27:00

标签: python python-3.x multiprocessing pickle

这是我的代码

class MusicHandler(object):
    """ Implements the logic to download musics """

    def __init__(self):
        """ Creates the class object, loads configs, absolute paths and create directories. Does not init download """
        # create logger
        self.logger = getLogger("music logger")
        self.logger.info("Initializing MusicHandler class object")
        # load config vars
        self.configs = utils.get_configs()
        # load absolute paths
        self.dir_music = self.configs["music_path"]
        self.dir_audio = utils.get_path_from_rel(self.configs["audio_path"], base_path=self.dir_music)
        self.dir_video = utils.get_path_from_rel(self.configs["video_path"], base_path=self.dir_music)
        self.taboo_path = utils.get_path_from_rel(self.configs["taboo_path"])
        # make dir if not exists
        list(map(utils.make_dir_safe, (self.dir_music, self.dir_audio, self.dir_video)))

    @run_safe
    def download_one(self, link, keep_video=False):
        """ handles the download of one link. keep_video determines if video is saved or deleted. """
        self.logger.info(f"Starting download of {link}")
        if self.is_taboo(link):
            self.logger.warning("Link is taboo, will skip it.")
            return
        name = self.download_video(link)
        self.logger.info(f"Download of {name} (video) was a success.")
        self.video_to_audio(name)
        self.add_to_taboo(link)
        if not keep_video:
            self.remove_video(name)
        self.logger.critical(f"Successfully downloaded {name}. Available at {self.dir_music}.")

    def get_musics_linear(self, url_list):
        """ Linear download of all links from list """
        for link in url_list:
            self.download_one(link)

    @run_safe
    def get_musics_parallel(self, url_list, num_procs=3):
        """ Parallel download of  all links from list """
        with Pool(num_procs) as p:
            print("here")
            p.map(self.download_one, url_list)
            print("there")

    def is_taboo(self, link):
        """ Verifies if link exists in the taboo file """
        return utils.is_in_file(self.taboo_path, link)

    def add_to_taboo(self, link):
        """ Adds link to the taboo file """
        utils.append_to_file(self.taboo_path, link)

    def download_video(self, link):
        """ Downloads the highest resolution video given a link. Returns file name """
        yt = YouTube(link)
        yt.streams.filter(progressive=True).order_by("resolution").desc().first().download(self.dir_video, yt.title)
        return utils.safe_filename(yt.title)

    def download_audio(self, link):
        """ Downloads only the audio of a given link. Returns file name """
        yt = YouTube(link)
        yt.streams.filter(only_audio=True).first().download(self.dir_audio, yt.title)
        return utils.safe_filename(yt.title)

    def video_to_audio(self, name):
        """ Converts a video to an audio file """
        self.logger.info("Converting video to audio.")
        video_f_path = os.path.join(self.dir_video, "{}{}".format(name, ".mp4"))
        audio_f_path = os.path.join(self.dir_audio, "{}{}".format(name, ".wav"))
        cmd_list = ["ffmpeg", "-i", video_f_path, "-f", "wav", "-ab", "19200", "-vn", audio_f_path]
        FNULL = open(os.devnull, 'w')
        subprocess.call(cmd_list, stdout=FNULL, stderr=subprocess.STDOUT)

    def remove_video(self, name):
        """ Deletes a video file """
        self.logger.info("Removing video file.")
        video_f_path = os.path.join(self.dir_video, "{}{}".format(name, ".mp4"))
        if os.path.exists(video_f_path):
            os.remove(video_f_path)

运行此代码时,出现以下错误:

  

get_musics_parallel中的第143行“ C:\ Users \ Y \ PycharmProjects \ pyMusic \ lib \ pyMusic.py”       p.map(self.download_one,url_list)     地图中的文件“ C:\ Program Files(x86)\ Microsoft Visual Studio \ Shared \ Python36_64 \ lib \ multiprocessing \ pool.py”,行266       返回self._map_async(func,可迭代,mapstar,chunksize).get()     文件“ C:\ Program Files(x86)\ Microsoft Visual Studio \ Shared \ Python36_64 \ lib \ multiprocessing \ pool.py”,行644,在获取中       提高自我价值     文件“ C:\ Program Files(x86)\ Microsoft Visual Studio \ Shared \ Python36_64 \ lib \ multiprocessing \ pool.py”,第424行,在_handle_tasks中       放(任务)     发送中的文件“ C:\ Program Files(x86)\ Microsoft Visual Studio \ Shared \ Python36_64 \ lib \ multiprocessing \ connection.py”,行206       self._send_bytes(_ForkingPickler.dumps(obj))     转储中的文件“ C:\ Program Files(x86)\ Microsoft Visual Studio \ Shared \ Python36_64 \ lib \ multiprocessing \ reduction.py”,行51       cls(buf,protocol).dump(obj)   TypeError:无法腌制_thread.RLock对象

但是,如果我删除记录器,则代码执行不会有任何问题。

关于记录器为何导致此泡菜错误的任何想法吗? 该错误是在“ get_musics_parallel”函数上,并且发生在map(self.download_one,urllist)行上。

我尝试通过Google搜索此错误,但是与该泡菜错误有关的问题似乎与我的问题无关。

感谢您的帮助, 问候

4 个答案:

答案 0 :(得分:1)

您不是在某个地方使用multiprocessing模块吗?它要求线程/进程之间交换的数据是可选取的。

记录器使用RLock来保持进程的状态,因此不能被腌制。 Logger uses it,以便在整个脚本中获得多个记录器(或同一个记录器)时,可以做到不弄乱日志文件(或任何其他记录输出)的神奇效果。

答案 1 :(得分:0)

当我运行pyspark作业时遇到了这个问题,在该作业中我使用日志记录模块记录任务期间的信息。
火花日志显示了这样的信息“ _pickle.PicklingError:无法序列化对象:TypeError:无法腌制_thread.RLock对象”
Spark将在计算之前将变量强制转换为所有工作者,但是无法强制转换日志对象,从而导致此类错误。
删除所有日志记录用法后,错误消失了。
希望本技巧对您有所帮助。

答案 2 :(得分:0)

我发现相同的错误,但是在另一台计算机上的相同代码没有引发错误。

区别是:代码无法正常运行的机器正在使用python3.6.7 使用相同代码的机器正在使用python3.7.6

所以我的答案是:如果可能,请升级到python 3.7.6

不确定为什么会起作用。

答案 3 :(得分:0)

我在 Python 3.6.7 上运行多处理时遇到了同样的错误。当记录器从 args 列表中删除时,它起作用了。