Ошибка (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 шт):

Автор решения: Zhihar
#Откуда копируем
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()
→ Ссылка
Автор решения: CrazyElf

В общем, дело в следующем:

  • Сначала посмотрим на 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, но и туда тоже лишние кавычки передавать не надо, он их правильно не состыкует, если они есть.

→ Ссылка