Форум сайта python.su
Добрый день.
Господа, есть некий скрипт, вытаскивающий из mp3 файла теги и склеивает их в строку, далее создает папку os.mkdir() с именем в виде этой строки и перемещает в нее файл, теги которого были использованы.
Все работает, все хорошо. Но по непонятным мне причинам на некоторых файлах скрипт спотыкается.
Выдавая ошибку: ValueError: mkdir: embedded null character in path
Имя папки хранится в переменной и если эту переменную передать в print(), оно (имя) распечатывается. Тип данных тоже в порядке (строка). Никаких запретных (с точки зрения создания папки) символов в строке нет.
Ошибка вылетает именно в момент выполнения команды os.mkdir().
Поясните данная ошибка - результат передачи в os.mkdir() пустой строки? Или я не прав?
Самого текста скрипта под рукой нет (другой комп, другой город). Кто-то может что посоветовать, или пока нет всего кода не понятна проблема?
Офлайн
что бы не задавать такой вопрос на форуме нужно научиться отлаживать вашу программу. Оборачиваете ваш вызов mkdir в try except и когда произойдет ошибка делаете хоть принт хоть запись в файл с отладочной информацией, которая бы помогла вам разобраться в проблеме.
Но я поделюсь с вами и более нестандартными решениями - вы можете эту переменную упаковать с помощью pickle, а затем , загрузив его, более детально в режиме реального времени разобраться с вашей переменной что же с ней не так. Ну и воспроизводить вашу проблему вы сможете многократно и очень быстро.
А задавать вопрос так как вы его задали - это практически гадание.
Более опытные люди скажут что наверняка речь идет о винде и наверняка проблема с системным вызовов которому не понравился тот набор данных который ему прислали. С вашей стороны это звучит так - в тегах могут быть записан текст в разных кодировках - когда вы их считываете, вы вероятно переводите их в байты - ок ошибки тут не возникло, а про целостность и адекватность данных мы не говорим в этом месте (она уже нарушена наверняка) но вот при попытке использовать эту строку как названия файла (то есть передать ее ОС для создания записи в файловой системе) произошла ошибка.
Меня немного смущает что текст ошибки не ожидаемый, но без кода я не ручусь ничего говорить. Хотя и он может не помочь - ведь не совсем ясно что там с данными.
Как то так
Офлайн
SomethingButNotNickNameЗначит, из тегов попал нуль-символ в строку. Ты перед созданием имени на диске должен почистить строку от всего, что туда может попасть. Когда склеил строку из тегов, почисти её от лишних символов (отфильтруй только разрешённые).
Все работает, все хорошо. Но по непонятным мне причинам на некоторых файлах скрипт спотыкается.
Выдавая ошибку: ValueError: mkdir: embedded null character in path
Офлайн
Текст скрипта такой.
import re import shutil import os from mp3_tagger import VERSION_1, VERSION_2, MP3File def func_list_files(): """ Возвращает список файлов внутри папки, исключая файлы программы :return: None """ return [f for f in os.listdir('.') if os.path.isfile('.' + '\\' + f) and not f.endswith('.py') and not f.endswith('.exe')] def func_list_dirs(): """ Возвращает список папок внутри исходной :return: None """ return [f for f in os.listdir('.') if os.path.isdir('.' + '\\' + f)] def func_bad_name(name): exceptions = {'\\', '/', '|', '<', '>', '?', ':', '"', '*', '.'} return bool(set(name).intersection(exceptions)) def func_get_tags(var_file, var_version): """ Получает файл и возврящает список [артист, альбом] :param var_file: Файл для обратотки :param var_version: Версия тегов для работы :return: список тегов """ mp3 = MP3File(os.path.join('.', var_file)) mp3.set_version(var_version) return [mp3.artist, mp3.album, mp3.year] def func_main(): """ Читает теги mp3 файлов, создает папки с названиями исполнителя и альбома и перемещает файлы в соответствии с их тегами :return: None """ for file in func_list_files(): print(file) tags = func_get_tags(file, VERSION_2) if None in tags: tags = func_get_tags(file, VERSION_1) if None in tags: continue name = tags[0] + '-' + tags[2] + '-' + tags[1] exception_chars = '\\\/\|<>\?:"\*\.' find_exceptions = re.compile('([{}])'.format(exception_chars)) name = re.sub('\s+', ' ', name) if func_bad_name(name): name = re.sub(find_exceptions, '', name) name = re.sub('\s+$', '', name) try: print(name) os.mkdir(name) except FileExistsError: pass shutil.move(file, '.\\{}\\'.format(name)) input('press enter to exit') def func_main_reversed(): """ Функция обратная main :return: None """ path = os.getcwd() for folder in func_list_dirs(): print(folder) os.chdir('.\\{}'.format(folder)) for file in func_list_files(): print(file) shutil.move(file, path) os.chdir('..') os.rmdir(folder) input('press enter to exit') # func_main_reversed() func_main()
py.user.nextПроверка на запретные осуществляется. Если только я упустил какой-то, но вроде нет. И скрипт спотыкается на вполне простых именах (буквы, тире плюс цифры и ничего более).
Значит, из тегов попал нуль-символ в строку
JOHN_16Не совсем понял этот момент. Ну обернуть в try except понятно, а какую отладочную информацию вывести? Текст ошибки? - он и так выведется.
что бы не задавать такой вопрос на форуме нужно научиться отлаживать вашу программу. Оборачиваете ваш вызов mkdir в try except и когда произойдет ошибка делаете хоть принт хоть запись в файл с отладочной информацией, которая бы помогла вам разобраться в проблеме.
Отредактировано SomethingButNotNickName (Март 24, 2018 21:49:22)
Офлайн
SomethingButNotNickNameНадо не проверять запретные, а пропускать разрешённые из исходной строки в конечную. Сделай функцию, которая принимает входную строку, перебирает её символы и в выходную строку записывает только разрешённые символы (множество которых ты определяешь внутри функции, модуль string может пригодиться). Потом после получения исходной строки из тегов файла подавай её в эту фильтрующую функцию и на выходе она будет выдавать уже готовое имя для файла. Можно и две функции сделать: одна - фильтрует символы; другая - формирует имя файла из отфильтрованных символов, дописывая к ним что-нибудь ещё.
Проверка на запретные осуществляется.
Отредактировано py.user.next (Март 25, 2018 00:49:04)
Офлайн
SomethingButNotNickNameНапример содержание переменной, ее repr представление. Либо любую другую информацию что поможет для конкретно этой проблемы.
Что еще и как это вывести?
Офлайн