четверг, 11 апреля 2013 г.

iPython не грузится, не растёт кокос

Под влиянием замечательного поста решил попробовать автоматизировать часть рутинных задач при помощи python и его продвинутой оболочки iPython. Учитывая, что с Python’ом я до этого дел никаких не имел, для упрощения старта решил воспользоваться «всё-в-одном» паком под Windows Python(x,y).

Пак встал без проблем – без каких либо сообщений об ошибках или предупреждений. Однако попытка запуска ipython notebook сопровождалась вот такой гроздью сообщений об ошибках и чем-то странным в браузере:

ERROR:root:Uncaught exception GET /static/jquery/css/themes/base/jquery-ui.min.css?v=d1a93 (127.0.0.1)
HTTPRequest(protocol='http', host='127.0.0.1:8888', method='GET', uri='/static/jquery/css/themes/base/jquery-ui.min.css?v=d1a93', version='HTTP/1.1', remote_ip='127.0.0.1', body='', headers={'Accept-Language': 'ru-RU', 'Accept-Encoding': 'gzip, deflate', 'Host': '127.0.0.1:8888', 'Accept': '*/*', 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729)', 'Dnt': '1', 'Connection': 'Keep-Alive', 'Referer': 'http://127.0.0.1:8888/'})
Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\tornado\web.py", line 1042, in _execute
    getattr(self, self.request.method.lower())(*args, **kwargs)
  File "C:\Python27\lib\site-packages\tornado\web.py", line 1568, in get
    mime_type, encoding = mimetypes.guess_type(abspath)
  File "C:\Python27\lib\mimetypes.py", line 294, in guess_type
    init()
  File "C:\Python27\lib\mimetypes.py", line 355, in init
    db.read_windows_registry()
  File "C:\Python27\lib\mimetypes.py", line 259, in read_windows_registry
    for ctype in enum_types(mimedb):
  File "C:\Python27\lib\mimetypes.py", line 249, 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)

...




Как оказалось, к самому iPython эти ошибки не имеют никакого отношения. Проблема возникает при загрузке web-сервера Tornado - при попытке получить из реестра mime-типы. В ветке реестра  [HKEY_CLASSES_ROOT\CLSID{4063BE15-3B08-470D-A0D5-B37161CFFD69}\EnableFullPage\MIME]  почему-то оказались mime-записи, содержащие кириллицу.

Лечение было проведено методом «на авось» - элементы типа «видео/mpeg» были переименованы в «video/mpeg», а то, что переименовать не удалось, было просто удалено. После этого iPyton прекрасно запустился. Понятно, что какие вылезут в результате такого лечения косяки – не понятно. Пока, правда, всё прекрасно обходится без них :)

пятница, 5 апреля 2013 г.

Чтобы Backspace в Explorer стал "вверх"

Продолжаю обостраивать систему под себя. Цель: заставить Explorer переходить по клавише Backspace на один уровень иерархии вверх.

Когда-то именно так и было, но в Win7 (говорят, что это началось ещё в Vista, но с ней мне не довелось работать) в Explorer значение клавиши Backspace кардинально поменялось - она стала отправлять вас в "предыдущее место находжения", а не в родительский каталог. Это, то ли в силу мой привычки, то ли приёмов работы, меня стало откровенно раздражать. Довольно долгое гугление позволило обнаружить ответ. Собственно, там два ответа, но уменя без проблем запустился толь один - скачать и поместить в автозагрузку
Download HTGBack XP-Style Backspace Key

После этого привычный Backspace в Explorer наконец-то начинает вести себя привычным способом. К сожалению, при большом аптайме и после интенсивного использования виртуальной машины, Explorer перестаёт реагировать  на нажатие этой магической клавиши. Правда, кто тут виноват (виртуалка vs программа), установить вряд ли удастся да и не нужно - раз в месяц можно и перезагрузить, благо, по-настоящему долгих задач нет.

пятница, 29 марта 2013 г.

Переключение по Left Shift + Right Shift

Сочетание клавиш для переключения языка ввода (пусть будет "раскладки", хотя это и не совсем точно) - дело сугубо индивидуальное... Лично мне куда удобнее "два шифта" (правильно звучит вроде как по сочетанию L.Shift + R.Shift) - они больше, попадать по ним проще и быстрее, да и не нужно складывать всякие фигуры из множества пальцев.

Стандартным образом заставить Win работать таким образом не получится. В всяком случае, мне этого не удалось. Большинство форумчан настоятельно предлагают популярные же Arum Switcher или Punto... Но! Они предлагают массу вариантов, вот только искомого категорически не умеют. После довольно долгих поисков была обнаружена софтнина, которая делает почти то, что нужно:
keyla

К сожалению, в стандартном приветствии для ввода пароля придётся пользоваться одним из стандартных сочетаний - т.к. на этом этапе keyla ещё не загружена.

воскресенье, 14 октября 2012 г.

Двумерный динамический массив в C++ (из 1D): перегрузка оператора ()

В предыдущей статье было показано, как можно использовать одномерный массив в качестве двумерного. Одновременно был отмечен ряд недостатков такой реализации. Повторим их кратко:
  1. при "ручном пересчёте" есть вероятность "глупой ошибки" вроде опечатки и т.п.; 
  2. использование функции "удлиняет" форму записи и делает менее прозрачным для понимания код; 
  3. и "ручной пересчёт", и вызов функции выглядят непривычно по сравнению с традиционной адресацией двумерного массива "[][]".

В C++ существует возможность перегрузки операторов, которая позволяет задать собственное поведение операторов пользовательских типов. Т.к. переопределить операторы стандартных типов нельзя, то повлиять на поведение '[]' одномерного массива мы никак не можем. Поэтому, чтобу "подружить" одномерный массив с его интерпритацией в качестве двумерного, нам потребуется сделать специальный класс-обёртку, которая и будет реализовывать необходимое поведение.

Зададим для "обёртки" следующие ограничения:
  1. не занимается управлением памятью, в т.ч. не выделяет память под массив, не освобождает её;
  2.  при инициализации (на этапе декларации) получает в качестве входных параметров-констант А) адрес начала памяти (одномерного массива), Б) размерность массива (предполагаем матрицу квадратной);
  3. должна отражать поведение, как если бы использовался исходный указатель;
  4. должна позволять производить чтение и модификацию элемента массива.
В С++ оператор "[]" принимает только один параметр, в то время как нам требуется два - первый (по строкам) и второй (по столбцам). Поэтому для решения задачи в такой формулировке мы "[]" использовать не можем, зато оператор "()" принимает любое количество параметров.

Напомним, что проектируемый класс просто обёртка над уже существующим 1D массивом:
typedef long CT; // Cell Type of the array

     /* ... */

    CT *arr = new(nothrow) CT[n*n]; //pointer to 1D-array of n*n elements
    if(!arr){ // no memory allocated
        cout << "The array was not allocated" << endl;
        return 1;
    }

Создадим к показанному выше 1D-массиву класс-обёртку:
class arrWrapper{
  private:
    CT *const &arr_ptr; //pointer to 1D array of n*n size
    const long n; // dimension of the square matrix [n,n]


  public:
    arrWrapper(CT *const &ptr, const long N):arr_ptr(ptr), n(N) {};
    inline CT& operator()(const int i, const int j)const 
                                        { return arr_ptr[i*n+j]; };
};

Здесь
-arr_ptr - ссылка на указатель (ссылка на массив). Именно этим приёмом (ссылкой) гарантируется, что класс-обёртка отреагирует на изменение исходного указателя (одномерного массива). Пример: память исходного массива была освобождена, а указатель установлен в NULL. Тогда, если по ошибке будет использована обёртка, произойдёт исключение по разыменованию NULL-указателя. Второй эффект такой реализации: если исходный указатель будет указывать на новый участок памяти (допустим, другой массив и т.п.), то и "обёртка" будет указывать туда же. При этом она будет считать, что размерность нового массива полностью соответствует старому!
-n - размерность массива [n,n]. Объявлена константой, т.к. изменение размерности у исходного массива произойти не может - для этого нужно выделить новую область памяти, скопировать туда данные, а затем освободить "старую" область.
arr_ptr и n размещены с секции private, чтобы избежать случайной порчи этих членов класса - вся работа с ними скрыта от пользователя. Более того, само это сокрытие, т.е. предоставление прозрачного интерфейса для обращения по индексам (и сокрытие механизма пересчёта индексом) и является целью создания класса-обёртки.
-arrWrapper(CT *const &ptr, const long N) - конструктор, принимающий в качестве параметров указатель (ссылку на указатель) на выделенную область памяти и соответствующий ей размер двумерного массива. Т.к. изменять значения этих параметров в процессе инициализации не требуется, они имеют квалификатор const.
- CT& operator()(const int i, const int j)const - определённая нами версия оператора (), которая и осуществляет пересчёт "двумерного" индекса в "одномерный". По реализации полностью совпадает с функцией пересчета из предыдущего поста. Обращение к элементу будет осуществляться как wrp(i,j), где wrp - "связанная" с некоторым одномерным массивом "обёртка".

Полный пример создания и использования двумерного динамического массива (на основе 1D-массива и перегрузки оператора ())

#include<stdio.h>   //to use memset
#include<iostream>  //to use cin, cout

typedef long CT; // Cell Type of the array

class arrWrapper{//Wrapper for 1D array
  private:
    CT *const &arr_ptr; //pointer to 1D array of n*n size
    const long n;       // dimension of the square matrix [n,n]

    arrWrapper& operator=(arrWrapper &)const{}; //to prevent 
              //default '=" operator, not needed to show the ()

  public:
    arrWrapper(CT *const &ptr, const long N):
                            arr_ptr(ptr), n(N) {};
    inline CT& operator()(const int i, const int j)const 
                            { return arr_ptr[i*n+j]; };
};


int main (int argc, char** argv)
{
    long n = 0; //variable to obtaint 2D-array size

    using namespace std; // to be able to use cin & cout
    cout << "Please, inter the matrix size n = ";

    //GET ARRAY SIZE
    cin >> n;      // read size n from keyboard

    //GET MEMORY FOR 1D ARRAY OF n*n SIZE
    CT *arr = new(nothrow) CT[n*n]; //pointer to 1D-array 
                                    //of n*n elements
    if(!arr){ // no memory allocated
        cout << "The array was not allocated" << endl;
        return 1;
    }

    //Fill array with char(0) values for sizeof(int)*n*n bytes
    memset(arr, static_cast<char>(0), 
           (sizeof(long)/sizeof(char))*n*n);

    //************************************************
    //INIT ('link') WRAPPER WITH THE 1D ARRAY and SIZE
    //************************************************
    //DECLARE WRAPPER
    arrWrapper wrp(arr, n);//derlare & init with array 

    //USE WRAPPER
    for (int i = 0; i < n; ++i){
       for(int j = 0; j < n; ++j){
           //ACCESS ELEMENT [i,j] USING the WRAPPER 
           wrp(i,j) = 10000*i+j;
       }
    }

    //FREE MEM
    delete [] arr;
    arr = NULL;

среда, 26 сентября 2012 г.

Двумерный динамический массив в C++: эмулирование одномерным массивом

Этот пост - первый в коллекции "велосипедов" по работе с двумерными массивами в С++. Оказалось, что удобно иметь место, куда можно послать и где держать краткое описание с пояснениями. Гугление же как правило выдаёт не очень хороший результат: нужное в нём найти можно, но много мусора, а велосипед чаще всего оказывается "не той системы".

Известно, что в С++ поддерживаются команды динамического выделения непрерывной области памяти - под одномерные массивы, для чего сущестует расширенный "квадратными скобками" синтаксис операторов new и delete

  int *iptr = new int[100];//get memory for 100 elements
  delete [] iptr; //free memory

Ожидания многих новичков не оправдываются - оператор для двумерного массива в языке отсутсвует, т.е.
  new int[100][100];//!error
просто ошибка. С другой стороны, он особенно и не требуется, поскольку динамические массивы любой размерности прекрасно создаются при помощи одномерного массива. Для этого достаточно помнить, что в С/С++ массивы хранятся по строкам (в отличие от, например, фортрана). Это значит, что двумерная матрица
   1 2 3
   4 5 6
хранится как одномерный массив
   1 2 3 4 5 6

Иногда после этого начинающий в С/С++ пытается создать одномерный динамический массив и присвоить указатель на него переменной типа двумерного массива (или указателя на указатели)
  int **ptr = NULL;
  int *iptr = new int[100*100];
  ptr = iptr; //!error
Такое присваивание не позволит сделать компилятор, кроме случая явного приведения int** к int*. Но в последнем случае хотя и не будет происходить ошибки на стадии компиляции, при выполнении (как минимум на операциях записи в массив) программа будет остановлена по нарушению доступа к памяти. Это произойдёт потому, что в ptr[i][j] значение из ptr[i] будет рассматриваться как адрес одномерного массива длиной [j]. Поэтому мы не можем использовать нотацию [][] и должны самостоятельно пересчитивать индекс элемента внутри одномерного массива.
Если m и n - размерность требуемого двумерного массива (т.е. число строк и столбцов), то пересчет индексов (обращение к [i,j]-тому элементу) можно осуществлять как
  iptr[i*n+j]

Полный пример создания и использования двумерного динамического массива (на основе 1D-массива)

#include<stdio.h>   //to use memset

typedef long CT; // Cell Type of the array

///////////////////////////////////////////
//   Main function demonstrate 2D array  //
///////////////////////////////////////////
int main (int argc, char** argv)
{
    long n = 10; //variable to obtain 
                 //2D [n,n]-array size.
                 //Input is better, 
                 //but for example purposes
                 //we don't use io routines. 

    //HERE WE GET ARRAY
    //Pointer to and memory allocation for
    //1D-array of n*n elements
    CT *arr = new(nothrow) CT[n*n]; 

    if(!arr){ // no memory allocated
        return 1; //STOP. Put here your code
                  //for no-memory case.
    }

   //Fill array with char(0) values
   //for sizeof(int)*n*n bytes,
   //i.e. init memory with zeroes. 
    memset(arr, static_cast<char>(0),        
           (sizeof(long)/sizeof(char))*n*n);

    //and HERE WE USE ARRAY
    for( int i = 0; i < n; ++i){
       for( int j = 0; j < n; ++j){
           //set arr[x][y] => arr[x*n+y]
           arr[i*n+j]=i*100+j; //write some
       }
    }

    //Free memory when you don't need it 
    delete [] arr; 

    //Set pointer to the de-allocated chunk
    //of memory to NULL to prevent 
    //misuse of already freed memory.
    arr = NULL;

    return 0;
}

С другой стороны, приходится постоянно вручную писать пересчёт индексов [i*n+j], что черевато опечатками и как следствие плохо диагностируемымы ошибками. Поэтому иногда предпочитают определить функцию пересчёта индексов для иключения таких ошибок, например
inline CT& element(const int i, const int j, 
                   CT*const arr, 
                   const int size)
{
    return arr[i*size+j];
}

Тогда цикл обращения будет выглядеть как
    //and HERE WE USE ARRAY
    for( int i = 0; i < n; ++i)
       for( int j = 0; j < n; ++j)
           element(i,j,arr,n) = i*100+j;

Обратим внимание, что функция возвращает ссылку (CT&) на элемент массива, и именно это обеспечивает возможность присваивания element(i,j,arr,n) = 1. Если же возвращать не ссылку на значение, а значение типа CT, то изменять значения элемента массива не получится (хотя чтение так же как и в верхнем случае будет выполняться нормально). Передаваемые же в функцию параметры объявлены константными (const) "для порядку", т.к. внутри функции мы их не меняем.

понедельник, 23 мая 2011 г.

Как спрятать текст под кат

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

Собственно, прилично описание subj последний раз нашел здесь.

А потом обнаружил, что блоггер это уже давно сам умеет...

четверг, 18 ноября 2010 г.

GMT: установка

В этой статье мы обойдем вниманием стандартную процедуру установки GMT, которая вполне хорошо документирована как на оригинальном сайте, так и на сайтах многих пользователей (например). Типичные проблемы связаны с зачастую неспособностью нового пользователя указать (т.е. ответить на вопросы инсталлятора) правильные расположения библиотек и отследить зависимости. Это вполне объяснимо: новичку просто надо курить маны. Опытному же исследователю жаль тратить свое время на выполнение рутинных задач (для автоматизации которых требуется некоторый навык и умения, ни как не связанные с процессом исследования). Специально для этого случая существует rpm.
Все, что вам остается:
добавить репозиторий в список repo менеджера пактов вашего дистрибутива.
Запустить установку. При этом будут скачаны не только последние доступные версии, но и отслежены все зависимости.

Итак,
заходим на http://software.opensuse.org/
вводим в поисковую строку GMT
выбирает свой дистрибутив
Производим поиск — и установку нужной версии.

PS
Надеюсь, теперь вы не будете верить, что установка GMT - это сложно, непонятно и неприятно. Ведь все так просто