среда, 20 октября 2010 г.

Изменился формат вывода bytea в PostgreSQL 9.0

После перехода на PostgreSQL 9, в одном из приложений, в разработке которого я учавствую, начала возникать ошибка при получении и десериализации данных, которые хранятся в базе данных в поле типа byte. В приложении используется библиотека Npgsql.

Причиной возникновения ошибки стало изменение формата вывода данных типа bytea. До версии PostgreSQL 9 форматом вывода по умолчанию был escape. Начиная с версии PostgreSQL 9 форматом вывода по умолчанию стал hex. Библиотека Npgsql этих изменений еще не учитывает.

Я нашел два способа решения этой проблемы. Первый, это изменение параметра bytea_output в конфигурационном файле postgresql.conf. Нужно убрать комментарий и установить значение escape. Второй способ, это в клиентском коде преобразовать массив из hex-формата в обычный массив байт. Что из себя представляет hex-формат можно прочитать здесь. Вот быстро набросанный код, который получает исходный массив байт:


  1. using (var reader = command.ExecuteReader())
  2. {
  3.   reader.Read();
  4.   data2 = (byte[])reader[0];
  5.  
  6.   byte[] data3 = new byte[(data2.Length - 1) / 2];
  7.   for (int i = 0; i < data3.Length; ++i)
  8.   {
  9.     var hi = byte.Parse(((char)data2[(i + 1) * 2 - 1]).ToString(), NumberStyles.AllowHexSpecifier);
  10.     var lo = byte.Parse(((char)data2[(i + 1) * 2]).ToString(), NumberStyles.AllowHexSpecifier);
  11.     data3[i] = (byte)((hi << 4) | (lo & 0x0F));
  12.   }
  13. }

Скорее всего есть более цивилизованные способы, но я их пока не нашел. :)

понедельник, 4 октября 2010 г.

Ресурс с статьями и примерами исходных кодов

На stackoverflow.com нашел ссылку на интересный ресурс Programming tutorials and source code examples. Наверное, у каждого программиста есть набор собственных шаблонов, готовых решений. На java2s.com собрано большое количество примеров на разных языках программирования. Начиная c примеров работы с памятью в C и заканчивая шаблонами HTML+CSS.

пятница, 30 июля 2010 г.

Python. Масштабирование изображений

С целью изучения Python-а слелал поделку для изменения размеров фотографий в пакетном режиме.

Для работы с изображениями я использовал библиотеку PIL. В Ubuntu эта библиотека предустановлена. В Windows нужно устанавливать самостоятельно. Я использую Python версии 2.7 под Windows. PIL для работы с Python 2.7 можно скачать с effbot.org.

Вот код сценария:

# Resize image

# Command line:
# python imgresize.py -d <directory> -p <percentage>

import os, sys
from PIL import Image

directory_ = sys.argv[sys.argv.index("-d") + 1]
percentage_ = int(sys.argv[sys.argv.index("-p") + 1])

filenames_ = os.listdir(directory_)

for filename_ in filenames_[:]:
    path_ = directory_ + "\\" + filename_
    if not os.path.isfile(path_):
        continue
    try:
        image_ = Image.open(path_)
        size_ = (image_.size[0] * percentage_ / 100, image_.size[1] * percentage_ / 100)
        if percentage_ < 100:
            image_ = image_.resize(size_, Image.ANTIALIAS)
        else:
            image_ = image_.resize(size_, Image.NEAREST)
        image_.save(directory_ + "\\r_" + filename_)
        print path_, "=>", "r_" + filename_, " OK "
    except:
        print path_, "\n", sys.exc_info()
    
print "Finish" 

Параметры командной строки описаны в начале сценария. Сценарий принимает два обязательных параметра: -d – путь, -p – новый размер изображения в процентах. Пример вызова:

python imgresize.py –d «C:\Photos» –p 50

В результате выполнения сценария в каталоге «C:\Photos» будут созданы файлы с именами начинающимися на «r_» и размером в два раза меньше исходных.

среда, 7 июля 2010 г.

Ошибка UnicodeDecodeError в демонстрационном проекте Django

Буквально на днях начал осваивать web-программирование. Начать решил с Python 2.7 + Django 1.1. После прочтения введений восхищению не было предела (оно есть до сих пор). 


Трудность появилась при попытке реализовать пример, приведенный в введении в Django. Трудность заключалась в том, что при попытке загрузить войти в административную часть новосозданного сайта, все отображалось не так как в примерах, а без стилей. При этом в журналах отладочного сервера выдавалось следующее сообщение:

Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\django\core\servers\basehttp.py", line 280, in run
    self.result = application(self.environ, self.start_response)
  File "C:\Python27\lib\site-packages\django\core\servers\basehttp.py", line 709, in __call__
    mime_type = mimetypes.guess_type(file_path)[0]
  File "C:\Python27\lib\mimetypes.py", line 295, in guess_type
    init()
  File "C:\Python27\lib\mimetypes.py", line 356, in init
    db.read_windows_registry()
  File "C:\Python27\lib\mimetypes.py", line 261, in read_windows_registry
    for ctype in enum_types(mimedb):
  File "C:\Python27\lib\mimetypes.py", line 251, in enum_types
    ctype = ctype.encode(default_encoding) # omit in 3.x!
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe0 in position 0: ordinal not in range(128)


Наличие исходников стандартной библиотеки Python-а позволило найти проблему довольно быстро. Я использую Windows XP. В моем случае проблема заключалась в том, что в реестре в разделе [HKEY_CLASSES_ROOT\CLSID\{4063BE15-3B08-470D-A0D5-B37161CFFD69}\EnableFullPage\MIME] содержались подразделы содержащие в названии кириллицу. При удалении этих разделов они автоматически пересоздавались. Поэтому помогло переименование, просто заменил кириллицу латиницей.

Понятно, что это частный случай и настройки системы. Но возможно, эта заметка позволит кому-нибудь сэкономить время.

--

Mihail 2 ноября 2012 г., 22:06

Для тех у кого в registry Windows 7 нет русских ключей, но проблема осталась - переименуйте сетевое имя компьютера с русского на английский языки.

--


Casufi5 декабря 2012 г., 19:06

Решение исправлением библиотеки: http://softwaremaniacs.org/forum/django/31707/

суббота, 29 мая 2010 г.

Простота программного кода

Простота программного кода - существенный фактор, который облегчает дальнейшее его сопровождение.

пятница, 2 апреля 2010 г.

Как открыть консоль из проводника

Иногда бывает нужно выполнить какую-нибудь операцию в консольном окне. При этом желательно открыть консольное окно в текущей папке проводника Windows. Для того чтобы это сделать, нужно зажать клавишу Shift и правой клавишей мыши открыть контекстное меню для нужной папки. При этом в контекстном меню будет доступен пункт 'Open command window here'.

вторник, 2 марта 2010 г.

Утилита Wixsubst

Для создания пакетов инсталляции я использую WiX. На мой взгляд, это простой, удобный и интенсивно развивающийся инструмент с хорошими возможностями. Для того чтобы ускорить процесс разработки своих WiX-проектов я написал небольшую утилиту wixsubst.

Утилита wixsubst предназначена для автоматической герерации WiX-кода на основании списка файлов на диске. Уже существует утилита paraffin, которая решает эту задачу. Но она предполагает ведение файла-шаблона. А это, на мой взгляд, не всегда удобно.

Когда я решил написать свою утилиту, я хотел решить следующие задачи:

  1. удобный вызов из редактора; в качестве параметра можно передать только имя WiX-файла;
  2. простые правила написания шаблона;
  3. возможность многократно вызывать утилиту для одного и того же WiX-файла для обновления списка файлов проекта;

Утилита работает следующим образом. Список файлов формируется на основании XML-комментария. XML-комментарий разбит на две части, заголовок и окончание. В заголовке описываются параметры. При вызове утилиты выполняется замена кода между заголовком и окончанием. Вложенные XML-комментарии не поддерживаются.

    ***

    Пример

Нужно создать пакет инсталляции для проекта:

C:\MyProject\MyProject.exe
C:\MyProject\MyProject.exe.config
C:\MyProject\Lib\Lib1.dll
C:\MyProject\Lib\Lib1.xml
C:\MyProject\Lib\Lib2.dll
C:\MyProject\Lib\Lib2.xml

Для этого в WiX-файле "myproject.wix" пишу следующий код:

...
<Directory Id="INSTALLLOCATION" Name="MyProject">

  <Component Id="ProjectFilesComponent" Guid="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx">
    <!--#def filesubst
    #def directory: C:\MyProject #end
    #def exclude: MyProject.exe #end
    #def subst: <File Sourse="%path%" Vital="yes"/>
    #end-->
    <!--#end filesubst-->
  </Component>
  <Directory Id="LibDirectory" Name="Lib">
    <Component Id="LibComponent" Guid="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx">
    <!--#def filesubst
    #def directory: C:\MyProject\Lib #end
    #def mask: *.dll #end
    #def subst: <File Id="%filename%" Source="%path%" Vital="yes"/>
    #end-->
    <!--end filesubst-->
    </Component>
  </Directory>
</Directory>
...

И вызываю wixsubst с параметром "myproject.wix". В результате вызова файл "myproject.wix" будет содержать следующий код:

...
<Directory Id="INSTALLLOCATION" Name="MyProject">

  <Component Id="ProjectFilesComponent" Guid="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx">
    <!--#def filesubst
    #def directory: C:\MyProject #end
    #def exclude: MyProject.exe #end
    #def subst: <File Sourse="%path%" Vital="yes"/>
    #end--><File Sourse="C:\MyProject\MyProject.exe.config" Vital="yes"/>
    <!--#end filesubst-->
  </Component>
  <Directory Id="LibDirectory" Name="Lib">
    <Component Id="LibComponent" Guid="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx">
    <!--#def filesubst
    #def directory: C:\MyProject\Lib #end
    #def mask: *.dll #end
    #def subst: <File Id="%filename%" Source="%path%" Vital="yes"/>
    #end--><File Id="Lib1.dll" Source="C:\MyProject\Lib\Lib1.dll" Vital="yes"/>
    <File Id="Lib2.dll" Source="C:\MyProject\Lib\Lib2.dll" Vital="yes"/>
    <!--#end filesubst-->
    </Component>
  </Directory>
</Directory>
...

Все повторные вызовы инструмента wixsubst, не будут модифицировать файл myproject.wix, пока не изменится список файлов проекта. Например, будет добавлена новая библиотека или конфигурационный файл.

    ***

Как показано в примере утилита wixsubst принимает один параметр - имя WiX-файла. Wixsubst можно вызвать и с двумя параметрами. В этом случае первый параметр будет именем файла-шаблона, а второй - именем результирующего файла.

Заголовок XML-комментария должен начинаться с ключевого выражения "#def filesubst". После ключевого выражения должно следовать описание параметров. Описание каждого параметра должно быть задано следующим образом "#def [имя параметра]: [значение параметра] #end".

Wixsubst поддерживает следующие параметры:

  • directory - папка из которой нужно получить список файлов, обязательный параметр;
  • exclude - список файлов, которые нужно исключить; файлы разделяются ";";
  • mask - маска файлов, которые нужно выбрать;
  • subst - шаблон кода WiX, который будет повторен для каждого найденного файла;

Шаблон, описанный в значении параметра subst может содержать специальные переменные "filename" и "path". Имя переменной нужно ограничивать символом "%". Вместо переменной filename будет подставляться имя файла без указания пути. Вместо переменной path будет подставляться имя файла с указанием пути.

Окончание XML-комментария представляет собой постоянное ключевое выражение "#end filesubst".

Для вызова утилиты из Visual Studio можно настроить External Tool (пункт меню Visual Studio Tools > External Tools, затем Add...). Пример настройки:


В результате появится пункт меню Tools > WixSubst. При выборе этого пункта меню будет обработан текущий WiX-файл.

Скачать утилиту можно здесь. Предложения, замечания приветствуются.