Копирование объектов, модуль copy
В Python изменяемые объекты нельзя скопировать, присвоив одну переменной другой, так как в этом случае копируется ссылка на объект, а не он сам. В итоге при изменении объекта через одну переменную, изменения видны через другую. Поэтому используются иные способы копирования, если оно действительно необходимо.
У списков, словарей и некоторых других встроенных типов есть метод copy() , создающий их поверхностную копию. В случае поверхностной копии, если объект является составным, то есть включает другие изменяемые объекты, то они не копируются, а копируются только ссылки на них.
Если же требуется полная копия объекта, следует воспользоваться функцией deepcopy() модуля copy . Кроме этой функции там также есть функция copy() , выполняющая поверхностное копирование, аналогичное методам copy() словарей и списков.
Разницу между copy() и deepcopy() иллюстрирует пример:
>>> import copy >>> nums = [1, 2, 3] >>> data = >>> data >>> data_copy = copy.copy(data) >>> data_deep = copy.deepcopy(data) >>> data_copy >>> data_deep >>> data_copy['a'] += 2 >>> nums[1:1] = [254] >>> data >>> data_copy >>> data_deep
В случае с deepcopy() была создана копия вложенного списка, copy() этого не делает.
Отсутствие переменной у списка вовсе не изменяет ситуацию:
>>> d = >>> c = copy.copy(d) >>> c >>> c[1].append(3) >>> c >>> d
Оператор is проверяет проверяет ссылаются ли две переменные на один объект, оператор == проверяет равенство значений.
>>> d = >>> c = d >>> e = d.copy() >>> d is c True >>> d is e False >>> d == e True
С помощью функций модуля copy можно копировать объекты собственных классов:
import copy class A: def __init__(self): self.lst = [] a = A() a.lst.append(10) b = copy.copy(a) b.lst[0] = 20 print(a.lst, b.lst) print(a is b) print(a) print(b)
[20] [20] False
Как мы видим, несмотря на то, что объекты a и b разные, поле lst обоих ссылается на один и тот же список. Чтобы при копировании объекта список был также скопирован, следует использовать функцию deepcopy() .
Модуль copy — поверхностное и глубокое копирование объектов

Операция присваивания не копирует объект, он лишь создаёт ссылку на объект. Для изменяемых коллекций, или для коллекций, содержащих изменяемые элементы, часто необходима такая копия, чтобы её можно было изменить, не изменяя оригинал. Данный модуль предоставляет общие (поверхностная и глубокая) операции копирования.
copy.copy(x) — возвращает поверхностную копию x.
copy.deepcopy(x) — возвращает полную копию x.
Исключениеcopy.error — возникает, если объект невозможно скопировать.
Разница между поверхностным и глубоким копированием существенна только для составных объектов, содержащих изменяемые объекты (например, список списков, или словарь, в качестве значений которого — списки или словари):
- Поверхностная копия создает новый составной объект, и затем (по мере возможности) вставляет в него ссылки на объекты, находящиеся в оригинале.
- Глубокая копия создает новый составной объект, и затем рекурсивно вставляет в него копии объектов, находящихся в оригинале.
Для операции глубокого копирования часто возникают две проблемы, которых нет у операции поверхностного копирования:
- Рекурсивные объекты (составные объекты, которые явно или неявно содержат ссылки на себя) могут стать причиной рекурсивного цикла;
- Поскольку глубокая копия копирует всё, она может скопировать слишком много, например, административные структуры данных, которые должны быть разделяемы даже между копиями.
Функция deepcopy решает эти проблемы путем:
- Хранения «memo» словаря объектов, скопированных во время текущего прохода копирования;
- Позволения классам, определенным пользователем, переопределять операцию копирования или набор копируемых компонентов.
Этот модуль не копирует типы вроде модулей, классов, функций, методов, следа в стеке, стековых кадров, файлов, сокетов, окон, и подобных типов.
Поверхностная копия изменяемых объектов также может быть создана методом .copy() у списков (начиная с Python 3.3), присваиванием среза (copied_list = original_list[:]), методом .copy() словарей и множеств. Создавать копию неизменяемых объектов (таких, как, например, строк) необязательно (они же неизменяемые).
Для того, чтобы определить собственную реализацию копирования, класс может определить специальные методы __copy__() и __deepcopy__(). Первый вызывается для реализации операции поверхностного копирования; дополнительных аргументов не передается. Второй вызывается для реализации операции глубокого копирования; ему передается один аргумент, словарь memo. Если реализация __deepcopy__() нуждается в создании глубокой копии компонента, то он должен вызвать функцию deepcopy() с компонентом в качестве первого аргумента и словарем memo в качестве второго аргумента.
Для вставки кода на Python в комментарий заключайте его в теги
Модуль shutil

Модуль shutil содержит набор функций высокого уровня для обработки файлов, групп файлов, и папок. В частности, доступные здесь функции позволяют копировать, перемещать и удалять файлы и папки. Часто используется вместе с модулем os.
Операции над файлами и директориями
shutil.copyfileobj(fsrc, fdst[, length]) - скопировать содержимое одного файлового объекта (fsrc) в другой (fdst). Необязательный параметр length - размер буфера при копировании (чтобы весь, возможно огромный, файл не читался целиком в память).
При этом, если позиция указателя в fsrc не 0 (т.е. до этого было сделано что-то наподобие fsrc.read(47)), то будет копироваться содержимое начиная с текущей позиции, а не с начала файла.
shutil.copyfile(src, dst, follow_symlinks=True) - копирует содержимое (но не метаданные) файла src в файл dst. Возвращает dst (т.е. куда файл был скопирован). src и dst это строки - пути к файлам. dst должен быть полным именем файла.
Если src и dst представляют собой один и тот же файл, исключение shutil.SameFileError.
Если dst существует, то он будет перезаписан.
Если follow_symlinks=False и src является ссылкой на файл, то будет создана новая символическая ссылка вместо копирования файла, на который эта символическая ссылка указывает.
shutil.copymode(src, dst, follow_symlinks=True) - копирует права доступа из src в dst. Содержимое файла, владелец, и группа не меняются.
shutil.copystat(src, dst, follow_symlinks=True) - копирует права доступа, время последнего доступа, последнего изменения, и флаги src в dst. Содержимое файла, владелец, и группа не меняются.
shutil.copy(src, dst, follow_symlinks=True) - копирует содержимое файла src в файл или папку dst. Если dst является директорией, файл будет скопирован с тем же названием, что было в src. Функция возвращает путь к местонахождению нового скопированного файла.
Если follow_symlinks=False, и src это ссылка, dst будет ссылкой.
Если follow_symlinks=True, и src это ссылка, dst будет копией файла, на который ссылается src
copy() копирует содержимое файла, и права доступа.
shutil.copy2(src, dst, follow_symlinks=True) - как copy(), но пытается копировать все метаданные.
shutil.copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, ignore_dangling_symlinks=False) - рекурсивно копирует всё дерево директорий с корнем в src, возвращает директорию назначения.
Директория dst не должна существовать. Она будет создана, вместе с пропущенными родительскими директориями.
Права и времена у директорий копируются copystat(), файлы копируются с помощью функции copy_function (по умолчанию shutil.copy2()).
Если symlinks=True, ссылки в дереве src будут ссылками в dst, и метаданные будут скопированы настолько, насколько это возможно.
Если False (по умолчанию), будут скопированы содержимое и метаданные файлов, на которые указывали ссылки.
Если symlinks=False, если файл, на который указывает ссылка, не существует, будет добавлено исключение в список ошибок, в исключении shutil.Error в конце копирования.
Можно установить флаг ignore_dangling_symlinks=True, чтобы скрыть данную ошибку.
Если ignore не None, то это должна быть функция, принимающая в качестве аргументов имя директории, в которой сейчас copytree(), и список содержимого, возвращаемый os.listdir(). Т.к. copytree() вызывается рекурсивно, ignore вызывается 1 раз для каждой поддиректории. Она должна возвращать список объектов относительно текущего имени директории (т.е. подмножество элементов во втором аргументе). Эти объекты не будут скопированы.
shutil.ignore_patterns(*patterns) - функция, которая создаёт функцию, которая может быть использована в качестве ignore для copytree(), игнорируя файлы и директории, которые соответствуют glob-style шаблонам.
shutil.rmtree(path, ignore_errors=False, onerror=None) - Удаляет текущую директорию и все поддиректории; path должен указывать на директорию, а не на символическую ссылку.
Если ignore_errors=True, то ошибки, возникающие в результате неудавшегося удаления, будут проигнорированы. Если False (по умолчанию), эти ошибки будут передаваться обработчику onerror, или, если его нет, то исключение.
На ОС, которые поддерживают функции на основе файловых дескрипторов, по умолчанию используется версия rmtree(), не уязвимая к атакам на символические ссылки.
На других платформах это не так: при подобранном времени и обстоятельствах "хакер" может, манипулируя ссылками, удалить файлы, которые недоступны ему в других обстоятельствах.
Чтобы проверить, уязвима ли система к подобным атакам, можно использовать атрибут rmtree.avoids_symlink_attacks.
Если задан onerror, это должна быть функция с 3 параметрами: function, path, excinfo.
Первый параметр, function, это функция, которая создала исключение; она зависит от платформы и интерпретатора. Второй параметр, path, это путь, передаваемый функции. Третий параметр, excinfo - это информация об исключении, возвращаемая sys.exc_info(). Исключения, вызванные onerror, не обрабатываются.
shutil.move(src, dst, copy_function=copy2) - рекурсивно перемещает файл или директорию (src) в другое место (dst), и возвращает место назначения.
Если dst - существующая директория, то src перемещается внутрь директории. Если dst существует, но не директория, то оно может быть перезаписано.
shutil.disk_usage(path) - возвращает статистику использования дискового пространства как namedtuple с атрибутами total, used и free, в байтах.
shutil.chown(path, user=None, group=None) - меняет владельца и/или группу у файла или директории.
shutil.which(cmd, mode=os.F_OK | os.X_OK, path=None) - возвращает путь к исполняемому файлу по заданной команде. Если нет соответствия ни с одним файлом, то None. mode это права доступа, требующиеся от файла, по умолчанию ищет только исполняемые.
Архивация
Высокоуровневые функции для созданиия и чтения архивированных и сжатых файлов. Основаны на функциях из модулей zipfile и tarfile.
shutil.make_archive(base_name, format[, root_dir[, base_dir[, verbose[, dry_run[, owner[, group[, logger]]]]]]]) - создаёт архив и возвращает его имя.
base_name это имя файла для создания, включая путь, но не включая расширения (не нужно писать ".zip" и т.д.).
format - формат архива.
root_dir - директория (относительно текущей), которую мы архивируем.
base_dir - директория, в которую будет архивироваться (т.е. все файлы в архиве будут в данной папке).
Если dry_run=True, архив не будет создан, но операции, которые должны были быть выполнены, запишутся в logger.
owner и group используются при создании tar-архива.
shutil.get_archive_formats() - список доступных форматов для архивирования.
shutil.unpack_archive(filename[, extract_dir[, format]]) - распаковывает архив. filename - полный путь к архиву.
extract_dir - то, куда будет извлекаться содержимое (по умолчанию в текущую).
format - формат архива (по умолчанию пытается угадать по расширению файла).
shutil.get_unpack_formats() - список доступных форматов для разархивирования.
Запрос размера терминала вывода
shutil.get_terminal_size(fallback=(columns, lines)) - возвращает размер окна терминала.
fallback вернётся, если не удалось узнать размер терминала (терминал не поддерживает такие запросы, или программа работает без терминала). По умолчанию (80, 24).
Для вставки кода на Python в комментарий заключайте его в теги
- Модуль csv - чтение и запись CSV файлов
- Создаём сайт на Django, используя хорошие практики. Часть 1: создаём проект
- Онлайн-обучение Python: сравнение популярных программ
- Книги о Python
- GUI (графический интерфейс пользователя)
- Курсы Python
- Модули
- Новости мира Python
- NumPy
- Обработка данных
- Основы программирования
- Примеры программ
- Типы данных в Python
- Видео
- Python для Web
- Работа для Python-программистов
- Сделай свой вклад в развитие сайта!
- Самоучитель Python
- Карта сайта
- Отзывы на книги по Python
- Реклама на сайте
Могу ли я просто скопировать модуль для python из старой папки в новую?
Я установил python на новый сервер и мне нужно обойти установление модуля requests. Он есть на другой машине. Можно ли просто скопировать файлы манульно? Будет ли все работать правильно или это не лучшая практика?
Отслеживать
user259379
задан 26 июл 2017 в 12:51
Superluminal Superluminal
938 6 6 серебряных знаков 27 27 бронзовых знаков
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
Pip freeze
По-моему, самое лучшее для новичка и лентяя - это делать pip freeze > requirements.txt , получим список установленных модулей с их версиями. После этого на новой машине делаем pip install -r requirements.txt , и подгружаем нужные нам модули с точно такими же версиями.
Virtualenv
Так же рекомендуется использовать virtualenv — это инструмент, позволяющий создавать виртуальные окружения с пакетами. Можно рассмотреть ее как своего рода "песочницу". Разные "песочницы" имеют разный набор пакетов разных версий. Плюс к этому уходит проблема засорения системы ненужными пакетами, так как "песочницы" можно легко создавать и удалять. В песочницу устанавливаются пакеты, которые необходимы для конкретной реализации. Используя два virtualenv на проект — одного чистого, содержащего минимальный набор зависимостей, и одного, предназначенного для разработки. Думаю, такой подход в любом случае не лишен смысла, так как вряд ли вы захотите тянуть на боевой сервер всевозможные моки и фреймворки для тестирования.
Статья о том как использовать virtualenv .
Python way
Чтобы объявить необходимые зависимости для своего пакета, можно указать их в install_requires в setup.py . И вообще написание для своего проекта setup.py - это лучшая практика, о чем написано в этой документации.