def imagefilename(im):
filename = im.getFilename()
if filename == None or len(filename) == 0:
filename = im.getName()+'.tga'
filename = os.path.join(tempfile.gettempdir(),
filename)
im.setFilename(filename)
im.save()
return filename
Когда мы загружаем файл на FTP-сервер, мы хотим убедиться, что мы не перезапишем существующий файл. Если мы обнаружим, что файл с данным именем уже существует, мы хотели бы иметь функцию, которая создаёт новое имя файла предсказуемым способом, похожим на то, как ведёт себя Блендер при создании имён для объектов Блендера. Мы хотели бы сохранять расширение файла, так что мы не можем просто прилепить к имени цифровой суффикс. Функция nextfile(), следовательно, сначала разделяет имя пути и часть с расширением. Она использует функции split() и splitext() из модуля os.path, чтобы оставить нам чистое имя.
Если имя уже заканчивается на суффикс, состоящий из точки и некоторого числа (например, .42), мы хотели бы увеличить это число. Это именно то, что выполняет довольно пугающая выделенная строка. Функция sub() модуля Питона re принимает регулярное выражение как первый аргумент (мы используем здесь сырую строку, так что нам не надо экранировать обратную косую черту), и проверяет, соответствует ли это регулярное выражение своему третьему аргументу (name, в данном случае). Регулярное выражение, используемое здесь, (\.(\d+)$) совпадает с точкой, за которой следуют одна или более десятичных цифр, но только, если эти цифры являются последними символами. Если есть соответствие образцу, он заменяется вторым аргументом функции sub(). В нашем случае, замена - это не простая строка, а лямбда-функция (то есть, безымянная), в которую мы передаём объект сопоставления, и ожидаем, что она вернёт строку.
Мы окружили часть цифр нашего регулярного выражения круглыми скобками, теперь мы можем просто извлечь эти цифры (без первоначальной точки), вызвав метод group() объекта сопоставления. Мы передаем ему 1 в качестве аргумента, так как первые открывающие скобки обозначают первую группу (группа 0 является всем образцом целиком). Мы преобразуем эту строку цифр в целое, используя встроенную функцию int(), добавляем к ней 1, и преобразуем её обратно в строку с функцией str(). До того, как этот результат автоматически будет возвращён из лямбда-функции, мы снова добавляем точку, чтобы соответствовать нашему желаемому образцу.
Мы завершаем проверкой, отличается ли результирующее имя от оригинального. Если они совпадают, значит оригинальное имя не соответствовало нашему образцу, и мы просто добавляем .1 к имени. Наконец, мы восстанавливаем полное имя файла, добавляя расширение, и вызывая функцию join() из модуля os.path, чтобы добавить путь платформо-независимым способом:
def nextfile(filename):
(path,base) = os.path.split(filename)
(name,ext) = os.path.splitext(base)
new = re.sub(r'\.(\d+)$',
lambda m:'.'+ str(1+int(m.group(1))),
name)
if new == name :
new = name + '.1'
return os.path.join(path,new+ext)
Теперь мы полностью готовы заняться реальной работой загрузки файла на FTP-сервер. Сначала мы удостоверимся, что наше окружение имеет переменную HOME, вызывая функцию sethome(). Затем, мы извлекаем имя хоста FTP-сервера, на который мы хотим загрузить (вполне законно, между прочим, ввести IP-адрес вместо имени хоста):
if __name__ == "__main__":
sethome()
host = getftphost()
Далее, мы извлекаем данные учётной записи пользователя для выбранного хоста из файла .netrc, если он присутствует (выделено). Это может закончиться неудачей по различным причинам (могло не быть .netrc-файла, или данные хоста отсутствуют в файле); в этом случае будет возбуждено исключение. Если это случится, мы сообщаем об этом пользователю и требуем имя пользователя и пароль с помощью всплывающего окна:
try:
(user,acct,password) = \