Автор: Ishayahu Lastov
Архив рубрики: Python
Программирование работы с SSH при помощи Paramiko (Перевод)
OpenSSH — это вездесущий метод удалённого безопасного доступа к машине и передачи файлов. Многие — системные администраторы, инженеры автоматизации тестов, веб-разработчики и другие люди используют этот методы ежедневно. Написание скриптов для ssh на Python может быть тяжёлым занятием, но модуль Paramiko позволяет решить эту задачу проще.
Python 101: Перемещение файлов между серверами (Перевод)
Пишем код
import paramiko
########################################################################
class SSHConnection(object):
""""""
#----------------------------------------------------------------------
def __init__(self, host, username, password, port=22):
"""Инициализируем и настраиваем соединение"""
self.sftp = None
self.sftp_open = False
# открываем поток SSH Transport
self.transport = paramiko.Transport((host, port))
self.transport.connect(username=username, password=password)
#----------------------------------------------------------------------
def _openSFTPConnection(self):
"""
Открываем SFTP соединение, если этого ещё не сделано
"""
if not self.sftp_open:
self.sftp = paramiko.SFTPClient.from_transport(self.transport)
self.sftp_open = True
#----------------------------------------------------------------------
def get(self, remote_path, local_path=None):
"""
Копируем файл с удалённого хоста к нам
"""
self._openSFTPConnection()
self.sftp.get(remote_path, local_path)
#----------------------------------------------------------------------
def put(self, local_path, remote_path=None):
"""
Копируем файл от нас на удалённый хост
"""
self._openSFTPConnection()
self.sftp.put(local_path, remote_path)
#----------------------------------------------------------------------
def close(self):
"""
Закрываем SFTP и ssh соединения
"""
if self.sftp_open:
self.sftp.close()
self.sftp_open = False
self.transport.close()
if __name__ == "__main__":
host = "myserver"
username = "mike"
pw = "dingbat!"
origin = '/home/mld/projects/ssh/random_file.txt'
dst = '/home/mdriscoll/random_file.txt'
ssh = SSHConnection(host, username, pw)
ssh.put(origin, dst)
ssh.close()
Итог
Дополнительное чтение
- Jesse Noller’s Программирование SSH при помощи Paramiko (Перевод)
Автор: Ishayahu Lastov
Зачем в python with
Долгое время при работе с файлами из python я писал примерно следующий код:
def some_func(fname):
fd = open(fname)
some_data_processing(fd.read())
return result
def some_func(fname):
fd = open(fname)
some_data_processing(fd.read())
return result
Тут предполагается, что в любом случае при выходе из функции переменная fd уничтожится и вместе с ней закроется файл и все будут жить долго и счастливо.
Но что будет если в some_data_processing произойдет исключение?
Например так:
import sysclass TestClass(object):
def __del__(self):
print «I’m deleted»
def data_process():
obj = TestClass()
raise IndexError()
try:
data_process()
except:
print «In exception handler»
print «after except»
import sysclass TestClass(object):
def __del__(self):
print «I’m deleted»
def data_process():
obj = TestClass()
raise IndexError()
try:
data_process()
except:
print «In exception handler»
print «after except»
На консоли появляется:
In exception handler
after except
I'm deletedПочему-то «In exception handler» и «after except» выводятся раньше «I’m deleted».
Первая проблема в том, что вместе с исключением питон хранит и трейс стека, содержащий все фреймы вплоть до породившего исключение. А внутри фрейма живет f_locals — словарь локальных переменных, и именно он имеет ссылку на экземпляр класса TestClass. Таким образом до окончания обработки исключения obj будет жить точно. Почему же «after except» появляется раньше чем «I’m deleted»? Было бы логично чистить трейс после успешного выхода из блока try. Дело в том что 2.X питон не всегда чистит внутренние структуры после обработки исключения и в общем случае вы должны явно вызывать функцию sys.exc_clear чтобы очистить их. Когда я подошел с этим вопросом к Larry Hastings (одному из основных разработчиков ядра питона) ему потребовалось около 20ти минут, что-бы понять что происходит и найти в документации sys.exc_clear. (Правда стоит отметить, что он давно использует 3.X, где это поведение стало адекватнее.) В 3.X это поведение улучшили, и теперь sys.exc_clear автоматически вызывается окончанию обработки исключения.
Кстати, если вы напишете примерно такой код:
try:
data_process()
except:
fr = sys.exc_info()[2]
del fr
try:
data_process()
except:
fr = sys.exc_info()[2]
del fr
то не забудьте удалить fr используя del, как в последней строке — иначе он образует циклическую ссылку с текущим фреймом и тогда все станет совсем плохо.
Стоит отметить, что подобное поведение проявляется не всегда. Например сл
Lviv.py #0
Видео — первая часть, вторая часть и презентация.
Автор: Andrew Svetlov
Метаклассы в python 2.X с примерами и полным разоблачением
Теория, часть 1. Метаклассы
Все начинается с объявления класса:
class A(object):
field = 12
def method(self, param):
return param + self.field
class A(object):
field = 12
def method(self, param):
return param + self.field
Имеющие опыт программирования на компилируемых языках могут увидеть здесь декларативную конструкцию, но это только обман зрения. В python всего две декларативные конструкции — объявление кодировки файла и импорт синтаксических конструкций «из будущего». Все остальное — исполняемое. Написанное объявление это синтаксический сахар для следующего:
txt_code = """
field = 12
def method(self, param):
return param + self.field
"""
class_body = {}
compiled_code = compile(txt_code, __file__, "exec")
eval(compiled_code, globals(), class_body)
A = type("A", (object,), class_body)
txt_code = """
field = 12
def method(self, param):
return param + self.field
"""
class_body = {}
compiled_code = compile(txt_code, __file__, "exec")
eval(compiled_code, globals(), class_body)
A = type("A", (object,), class_body)
Оба этих способа создать класс A совершенно эквивалентны. Окончательно убедиться в том, что объявление класса исполнимо можно посмотрев вот на это:
def this_is_not_cplusplus(some_base_class, num_methods):
class Result(some_base_class):
x = some_base_class()
for pos in range(num_methods):
# добавим функцию в locals - она попадает в тело
# класса Result и станет его методом
locals()['method_' + str(pos)] =
lambda self, m : m + num_methods
return Result
class_with_10_methods = this_is_not_cplusplus(object, 10)
class_with_20_methods = this_is_not_cplusplus(
class_with_10_methods, 20)
print class_with_10_methods().method_3(2) # напечатает 12
print class_with_20_methods().method_13(2) # напечатает 22
def this_is_not_cplusplus(some_base_class, num_methods):
class Result(some_base_class):
x = some_base_class()
for pos in range(num_methods):
# добавим функцию в locals - она попадает в тело
# класса Result и станет его методом
locals()['method_' + str(pos)] =
lambda self, m : m + num_methods
return Result
class_with_10_methods = this_is_not_cplusplus(object, 10)
class_with_20_methods = this_is_not_cplusplus(
class_with_10_methods, 20)
print class_with_10_methods().method_3(2) # напечатает 12
print class_with_20_methods().method_13(2) # напечатает 22
Функция this_is_not_cplusplus создает новый класс каждый раз, когда мы ее вызываем, используя переданный тип в качестве базового и создавая в н