Ошибка (OSError: [WinError 123]), из за чего возникает?
import os
import time
#Откуда копируем
source = ['"D:\Miscellanea\Резервные копии"']
#Куда копируем
target_dir = '"D:\Miscellanea\Backup Archive"'
#Название папки с сохраненым архивом резервных данных, в формате:
#%Месяц%День%Год
today = target_dir + os.sep + time.strftime('%m.%d.%Y')
#Создание имени zip-архива в формате %Час%Минута
now = time.strftime('%H-%M')
#Если в целевой папке нет каталога, создаем его
if not os.path.exists(today):
os.mkdir(today)
print('Идет процесс создания архива резервных данных, пожалуйста подождите...')
#Присваиваем имя архиву
target = today + os.sep + now + '.zip'
zip_command = "zip -qr {0} {1}".format(target, ' '.join(source))
if os.system(zip_command) == 0:
print('Архив резервных копий успешно создан в', target)
else:
print('Создание архива резервных копий НЕ УДАЛАСЬ')
Вижу что ругается на 20 строку, даже знаю как это исправить, изменить имя папки с Backup Archive на BackupArchive то есть убрать пробел, тогда все заработает, только вот у меня вопрос, по каким причинам так происходит, ведь в коде все в порядке, путь где есть пробелы нужно писать в "", это сделано, так почему происходит ошибка? И как можно было бы её обойти что ли

Ответы (2 шт):
#Откуда копируем
source = ['"D:\Miscellanea\Резервные копии"']
#Куда копируем
target_dir = '"D:\Miscellanea\Backup Archive"'
вы очень щедрый на кавычки человек :)
простой пример:
path = 'd:\\in put.txt'
fin = open(path, 'r', encoding='utf-8')
print(fin.readlines())
fin.close()
В общем, дело в следующем:
- Сначала посмотрим на
target_dir. Когда вы к этому пути ещё что-то пристыковываете, то наличие кавычек внутри строки "ломает" путь - по правилам кавычки должны быть в начале и в конце пути с пробелом, а после того, как вы что-то пристыковали в конец такой строки, кавычки оказались внутри пути, а не по краям, и получился неправильный путь. Кроме того, у командыos.mkdirнет проблем с пробелами внутри пути - она ведь получает параметр-строку, в которой нет ничего, кроме имени каталога, поэтому для неё не нужно обрамлять каталог с пробелом дополнительными кавычками, для неё вся полученная строка - это имя каталога, и не важно - есть там пробелы или нет. Таким образом, внутренние двойные кавычке в самомtarget_dirне нужны. Но поскольку вы потом используете полученный из негоtargetв командной строке - в момент формирования командной строки сzipкавычки придётся добавить вокруг значенияtarget. - Теперь посмотрим на
source. Пути, содержащиеся в этом списке, добавляются внутрь командной строки, в которой вызывается командаzipс параметрами и там уже без кавычек, обрамляющих путь к каталогу, утилитаzipникак не сможет понять - где начинается и где кончается путь с пробелом внутри, поэтому в этом случае кавычки обязательно нужны. Хотя их тоже можно было бы добавить уже в момент формирования командной строки.
"D:\Miscellanea\Backup Archive"\2020.10.26 - это кривой путь, получающийся в результате соединения пути с кавычками с другим путём
zip -qr "D:\Miscellanea\Backup Archive\file.zip" "D:\Miscellanea\Резервные копии" - как тут разобраться без кавычек, где что начинается и где кончается?
В общем, в вашем случае я бы добавил кавычки в target уже в момент формирования командной строки с zip, ну или сразу перед этим. Но не ранее того. Например, можно сделать так:
zip_command = 'zip -qr "{0}" {1}'.format(target, ' '.join(source))
И ещё тут нужно упомянуть, нормальный способ конкатенации путей каталогов - это через os.path.join, но и туда тоже лишние кавычки передавать не надо, он их правильно не состыкует, если они есть.
