2008-10-16

Тормозим оптический привод

Надоел шум нового супер-быстрого CD-ROM (DVD-ROM или пишущего комбайна) при просмотре фильма? Ограничиваем его скорость самым простым способом, который может прийти в голову:
$ eject -x8 /media/cdrom0
Где -x8 — скорость работы привода (при x32 мой привод шумит значительно меньше, почти не заметно, а при x16 его не слышно вообще, вы можете попробовать другие скорости), дальше — точка монтирования вашего устройства, либо это само устройство (/dev/hdc). Я пробовал работать только с точкой монтирования, хотя уверен, что и ссылка непосредственно на устройство, должна сработать. В любом случае, вам поможет гугль и:
$ man eject
Если я всё правильно помню, то первая скорость (CD-ROM Mode 1) это 150 килобайт/сек., т.е. 150 килобайт * 8 бит = 1.2 мегабита. Качество традиционных фильмов MPEG4 колеблется в пределах 700 килобит/сек. + звук, редко больше 128 килобит/сек. итого у нас выходит 828 килобит. Согласитесь, даже для первой скорости, запас очень не плохой. Вывод такой что вы можете не париться и ставить первую или вторую скорость, врядли какой-либо привод будет шуметь на такой скорости, а если диск не испорчен, вы посмотрите его нормально. Да и в повседневной жизни скорость можно уменьшать. Уверен что не всегда нужны обороты в x48 или больше, ведь основной проблемой будут не обороты диска, а перемещение головки — скорость вращения диска дает преимущества только при его последовательном чтении. В сети вы можете найти описание другого утиля для управление скоростью привода, но ни один из них, как и этот способ, не работают при использовании DVD-диска, не знаю в чем дело, но DVD, что очевидно, вращаются с максимальной скоростью и продолжают шуметь, что бы вы не делали.

p.s. Забыл сказать, что речь идет о Linux :-).

2008-10-10

Twisted-клиент и веб-прокси

Как это не парадоксально, но Twisted в своем арсенале не имеет средств для работы с HTTP через прокси-сервер. Я наклепал небольшой код, который решает эту проблему. Сделано не бог весть как, но если кому-то очень нужно, то сгодится и этот код.
from twisted.web import client as _twc


class HTTPPageGetter(_twc.HTTPPageGetter):

def sendCommand(self, command, path):
if self.factory.proxy:
from twisted.web.http import urlparse
from urlparse import urlunparse

domain = urlparse(self.factory.url)[:2]
path = urlparse(path)[2:]
path = urlunparse(domain + path)

self.transport.write('%s %s HTTP/1.0\r\n'%(command, path))

def handleStatus_301(self):
location = self.headers.get('location')
if not location:
self.handleStatusDefault()
return
url = location[0]

if self.followRedirect:
self.factory.connect(url)

else:
from twisted.python.failure import Failure
from twisted.web.error import PageRedirect

self.handleStatusDefault()
self.factory.noPage(Failure(
PageRedirect(self.status, self.message,
location = url)))

self.quietLoss = 1
self.transport.loseConnection()



class HTTPClientFactory(_twc.HTTPClientFactory):

protocol = HTTPPageGetter
proxy = None

def __init__(self, url, **kwargs):
self.proxy = kwargs.pop('proxy', None)
_twc.HTTPClientFactory.__init__(self, url, **kwargs)

def connect(self, url = None):
if url:
self.setURL(url)

if self.proxy is not None:
try:
host, port = self.proxy.split(':')
host, port = str(host), int(port)
except:
raise Exception(
'Incorrect proxy address "%s"'%self.proxy)

else:
host, port = self.host, self.port

from twisted.internet import reactor

if self.scheme == 'https':
from twisted.internet.ssl import ClientContextFactory

contextFactory = ClientContextFactory()
reactor.connectSSL(host, port, self, contextFactory)

else:
reactor.connectTCP(host, port, self)
Этот код вырван из контекста (моего проекта), так что я его не тестировал, если будут ошибки — обращайтесь, разберемся.
Для работы с этой HTTPClientFactory теперь не стоит использовать вызов reactor.connectTCP, для установления соединения вызовите метод connect этой фабрики, а так же, при создании фабрики, не забудьте указать какой прокси вы хотите использовать:
factory = HTTPClientFactory('http://python.su/',
proxy = 'localhost:3128')
factory.connect()

2008-10-09

Кодировка в html5lib

Есть такая замечательная библиотека html5lib, а предназначена она для обработки, в том числе не валидного (не корректного) HTML. Пакет так же имеет код для сериализации DOM, ElementTree, BeautifulSoup и другой хрени в HTML, но этой его частью я не пользуюсь.

Вот простенький пример, для парсинга HTML в DOM:
from html5lib.html5parser import HTMLParser
from html5lib.treebuilders.dom import TreeBuilder

dom = HTMLParser(tree = TreeBuilder).parse(html)
Где html — файловый объект или строка. Собственно это все.

Следует отметить, что это замечательная библиотека в состоянии самостоятельно определить кодировку документа одним из нескольких способов, в том числе «самым правильным», используя значение тега meta. Но вот незадача, «самый правильный» способ берет только первые 512 байт для анализа и, если заголовок большой и тег с указанием кодировки находится за границей в 512 байт, то кодировку определить нет шансов.

Решить проблему можно таким вот хаком:
from html5lib.inputstream import HTMLInputStream

HTMLInputStream.numBytesMeta = property(
lambda self: 1024,
lambda self, value: None)
HTMLInputStream.numBytesChardet = property(
lambda self: 2048,
lambda self, value: None)

del HTMLInputStream
Где numBytesMeta это и есть ограничение при сканировании meta, а numBytesChardet это ограничение при сканировании HTML другим методом, какой анализ проводится, я не разбирался. Эти атрибуты настраиваются при инициализации экземпляра HTMLInputStream и тут же используются, так что другого способа перекрыть эти значения нет, не считая, конечно, варианта с переопределением и полным переписыванием метода __init__ и использованием «хитрых свойств». Я умолчал про цифры в лямбдах, но вы и сами о их смысле догадываетесь.

2008-06-01

Удивительно безграмотный тест

По вопросам и результатам этого теста можно судить, что я обязан иметь лицензию на винду (и прочий коммерческий софт), даже если у меня её нет. Я обязан покупать игры и голливудские фильмы, когда они мне не нужны. А лицензионная чистота и страх перед законом превыше моей дружбы. Так то ;-).

Расписал по пунктам свои ответы.

SmartMoney
Пират ли вы?

Вы пират широкого профиля.
срок

SmartMoney, рассмотрев все обстоятельства дела, учтя как отягчающие (подчеркнув характер рецидивности совершенных преступлений и умышленность совершенных деяний), так и смягчающие вину обстоятельства (ваше чистосердечное признание), положительные характеристики, путем частичного сложения наказаний и, руководствуясь сложившейся судебной практикой, определил Ваш приговор: штраф 3 миллиона рублей и год тюрьмы.

Пройти тест

2008-05-10

SSH-туннель

Пару дней назад решал вопрос по подключению к удаленному MySQL серверу через SSH-туннель. По этому поводу решил разродиться короткой памяткой (для себя, для вас) о том как этот тунель организовать под Linux. Уверен, что установить и запустить SSH демон на сервере у вас не составит труда, так же вы уже установили клиент на своем клиенте. Вообще, все очень просто. Ни сервер, ни клиент, которые вы хотите подружить через туннель (я говорю о ПО, а не о машинах как таковых), не должны быть специально обучены работать с туннелем, они и знать о нем не будут. Все будет работать в штатном режиме, как будто и нет никакого туннеля. Что ж, делаем в своем любимом терминале, на клиентской машине, так:
$ ssh -f -N -L4787:example.org:8787 user@server.org

Все, теперь несколько комментариев:

  • 4787 - Этот порт будет открыт на локальной машине, используйте его для доступа к вашему серверу приложения (MySQL, PostgreSQL и т.д.), используйте тот клиент, который предназначен для работы с этим сервером.

  • example.org:8787 - Это удаленный сервер, общение с которым вы и шифруете. Понимайте так, что порт 8787 (в данном примере) на удаленной машине будет транслироваться в 4787 на вашем клиенте.

  • user@server.org - Тут все как обычно. Это машина, на которой установлен SSH-сервер, user - пользователь на этом сервере. Шифрованный канал будет организован именно до этой машины, а вот от неё до example.org трафик шифроваться не будет, будет использован уже ваш сетевой протокол. Обычно example.org и server.org это один и тот же сервер (конечно же используется одно и то же имя или localhost вместо example.org).


По всем остальным ключам и, если вам нужны подробности, обращайтесь к man'у:
$ man ssh
Туннель можно сделать и с помощью PuTTY - почитайте инструкцию по подключению к MySQL, там все можно по скринам понять, если у вас с английским туго.

p.s. Совсем забыл. Респект и уважуха нашим ветеранам. Всех с праздником.