#echo "message" | mutt -a /path/to/file/with/attachment -s "subject"
-- my@e.mail.address
#mutt -a /path/to/file/with/attachment -s "subject" -- my@e.mail.address
< /path/to/file/with/text
#echo "message" | mail -s "subject" my@e.mail.address
#mail -s "subject" my@e.mail.address < /path/to/file/with/text
среда, 10 июня 2015 г.
Как послать почтовое сообщение из командной строки UNIX
Существует много способов сделать это, конечно. Приведем примеры с использованием утилит mail и mutt:
понедельник, 1 июня 2015 г.
Python-программа с интерфесом Cocoa
Рассмотрим простейшую программу, написанную на питоне, но использующую интерфейс Cocoa. Достоинство питона, как известно, заключается в легкости его изучения и кроссплатформенности. Однако, если писать программу на питоне, то встает вопрос - какую оконную систему использовать. Если мы используем MacOS, то естественно, предпочтительно использовать Cocoa. Здесь рассматривается как соединить мощь питона и "внешний вид" Cocoa. Примеры компилировались на OS X Yosemite, Version 10.10.3.
Для начала нам необходимо установить последнюю версию питона. Для этого вытираем из файловой системы текущую версию питона.
#rm -rf /Library/Frameworks/Python.framework
#rm -rf /Applications/Python*
Для начала нам необходимо установить последнюю версию питона. Для этого вытираем из файловой системы текущую версию питона.
#rm -rf /Library/Frameworks/Python.framework
#rm -rf /Applications/Python*
#rm -rf /usr/local/bin/python*
Устанавливать питон предпочтительно утилитой brew. В принципе конечно можно устанавливать и другими путями: "вручную" - выкачивая прямо с домашней страницы с распаковкой по нужному пути; используя утилиту fink; или используя порты. Я предпочитаю brew. Если она еще не установлена, устанавливаем ее, нужно соединение с интернетом:
Устанавливать питон предпочтительно утилитой brew. В принципе конечно можно устанавливать и другими путями: "вручную" - выкачивая прямо с домашней страницы с распаковкой по нужному пути; используя утилиту fink; или используя порты. Я предпочитаю brew. Если она еще не установлена, устанавливаем ее, нужно соединение с интернетом:
#ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
Далее делаем следующую последовательность команд:
#brew doctor
#brew update
#brew install python
#brew install python3
Следим, чтобы значение переменной PATH (в нашем случае это /usr/local/bin) указывало на интерпретатор питона. Если нет - то делаем это вручную - редактируем .bash_profile (или .bash_login или .profile) - добавляем строку
export PATH=/usr/local/bin:/usr/local/sbin:$PATH
- и перелогиниваемся:
#echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/usr/texbin
#which python
/usr/local/bin/python
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/usr/texbin
#which python
/usr/local/bin/python
#which python3
/usr/local/bin/python3
Также интерпретатор находится по пути /usr/bin/python
/usr/local/bin/python3
Также интерпретатор находится по пути /usr/bin/python
brew проинсталлирует полезные для работы со средой питона утилиты pip и setuptools.
pip - это менеджер пакетов питона;
setuptools - это набор утилит для установки пакетов питона через сеть. Наиболее полезная из них - easy_install.
Обновим версию pip и setuptools до актуальной (версии, установленные brew могут отставать):
Обновим версию pip и setuptools до актуальной (версии, установленные brew могут отставать):
#pip install --upgrade pip setuptools
#pip3 install --upgrade pip setuptools
или:
#easy_install3 pip
или:
#easy_install3 pip
#brew linkapps python
#brew linkapps python3
Теперь, когда у нас установлен питон, нам надо "провести мост" для взаимодействия между ним и "родным" для MacOS языком objective-c. Это осуществляется модулем питона PyObjC. С помощью этого модуля мы имеем функции питона, вызывающие соответствующие функции objective-c. Устанавливаем:
#pip2 install -U pyobjc-core
#pip2 install -U pyobjc
Теперь мы имеем интерпретатор питона обоих версий (2-й и 3-й) по пути /usr/local/bin и директорию site-packages по пути /usr/local/lib/python[2.7-3.4]/site-packages со всеми необходимыми для нашей задачи модулями питона. Питон реально расположен по пути: /usr/local/Cellar/python[3]
Наконец мы можем приступить к нашей главной цели.
Открываем XCode и создаем новый пустой проект PyObjC.
Обобщенная схема наших действий будет следующая:
Создаем новый файл:
Код файла PythonCode.py:
Опять создаем новый файл:
Это файл с графическим интерфейсом. В пустое окно ложим три кнопки и текстовое поле. Две кнопки соответствуют методам нашего питоновского класса, текстовая метка соответствует полю нашего класса, а третья кнопка будет для выхода из приложения. Для установки данного соответствия методом drag&drop "соединяем" эти кнопки с иконкой File's Owner, кнопку выхода с методом terminate в иконке First Responder. Поле класса с меткой связываем используя drag&drop из иконки File's Owner в эту метку в диалоге. Вышеупомянутые элементы видны на следующем рисунке. Также необходимо при "активном" File's Owner наисать имя нашего питоновского класса в "Custom Class":
Обратите внимание, что XCode используется только для построения интерфейса. Питоновские файлы мы можем писать используя другие среды разработки. Здесь же в проете мы имеем только два файла: CocoaWindow.xib и PythonCode.py.
Теперь сохдадим файл setup.py:
В директории проекта из командной строки запускаем следующую команду:
#py2applet --make-setup PythonCode.py
Создается файл setup.py, который надо отредактировать, как обозначено цветом:
#vim setup.py
Последний шаг:
#python setup.py py2app -A
Если все сделано аккуратно, то появиться директория dist c нашим целевым приложением PythonCode.app, при запуске которого появится диалог с текстовым полем, где отображается цифра, которую можно менять, нажимая на две кнопки:
Признаю, что для чтения этот текст тяжел. Несмотря на то, что долго думал, как описать все эти действия. Особенно место, где обясняется работа с графическим интерфейсом, не очень удачно. Посмотрите англоязычное решение описанной задачи.
Теперь мы имеем интерпретатор питона обоих версий (2-й и 3-й) по пути /usr/local/bin и директорию site-packages по пути /usr/local/lib/python[2.7-3.4]/site-packages со всеми необходимыми для нашей задачи модулями питона. Питон реально расположен по пути: /usr/local/Cellar/python[3]
Наконец мы можем приступить к нашей главной цели.
Открываем XCode и создаем новый пустой проект PyObjC.
Обобщенная схема наших действий будет следующая:
- Создаем файл с питоновским кодом PythonCode.py c реализацией класса PythonClassForCocoa;
- Создаем файл setup.py;
- Создаем в XCode файл интерфейса CocoaWindow.xib;
- Создаем наше целевое приложение PythonCode.app;
Создаем новый файл:
Код файла PythonCode.py:
from Cocoa import *Обратите внимание на выделенные красным цветом участки кода.
from Foundation import NSObject
class PythonClassForCocoa(NSWindowController):
counterTextField = objc.IBOutlet()
def windowDidLoad(self):
NSWindowController.windowDidLoad(self)
# Start the counter
self.count = 0
@objc.IBAction
def increment_(self, sender):
self.count += 1
self.updateDisplay()
@objc.IBAction
def decrement_(self, sender):
self.count -= 1
self.updateDisplay()
def updateDisplay(self):
self.counterTextField.setStringValue_(self.count)
if __name__ == "__main__":
app = NSApplication.sharedApplication()
# Initiate the contrller with a XIB
viewController = PythonClassForCocoa.alloc().initWithWindowNibName_("CocoaWindow")
# Show the window
viewController.showWindow_(viewController)
# Bring app to top
NSApp.activateIgnoringOtherApps_(True)
from PyObjCTools import AppHelper
AppHelper.runEventLoop()
Опять создаем новый файл:
Это файл с графическим интерфейсом. В пустое окно ложим три кнопки и текстовое поле. Две кнопки соответствуют методам нашего питоновского класса, текстовая метка соответствует полю нашего класса, а третья кнопка будет для выхода из приложения. Для установки данного соответствия методом drag&drop "соединяем" эти кнопки с иконкой File's Owner, кнопку выхода с методом terminate в иконке First Responder. Поле класса с меткой связываем используя drag&drop из иконки File's Owner в эту метку в диалоге. Вышеупомянутые элементы видны на следующем рисунке. Также необходимо при "активном" File's Owner наисать имя нашего питоновского класса в "Custom Class":
Обратите внимание, что XCode используется только для построения интерфейса. Питоновские файлы мы можем писать используя другие среды разработки. Здесь же в проете мы имеем только два файла: CocoaWindow.xib и PythonCode.py.
Теперь сохдадим файл setup.py:
В директории проекта из командной строки запускаем следующую команду:
#py2applet --make-setup PythonCode.py
Создается файл setup.py, который надо отредактировать, как обозначено цветом:
#vim setup.py
"""
This is a setup.py script generated by py2applet
Usage:
python setup.py py2app
"""
from setuptools import setup
APP = ['PythonCode.py']
DATA_FILES = ['CocoaWindow.xib']
OPTIONS = {здесь пробел или пусто}
setup(
app=APP,
data_files=DATA_FILES,
options={'py2app': OPTIONS},
setup_requires=['py2app'],
)
Последний шаг:
#python setup.py py2app -A
Если все сделано аккуратно, то появиться директория dist c нашим целевым приложением PythonCode.app, при запуске которого появится диалог с текстовым полем, где отображается цифра, которую можно менять, нажимая на две кнопки:
Признаю, что для чтения этот текст тяжел. Несмотря на то, что долго думал, как описать все эти действия. Особенно место, где обясняется работа с графическим интерфейсом, не очень удачно. Посмотрите англоязычное решение описанной задачи.
воскресенье, 4 января 2015 г.
Лямбда выражения и алгоритмы STL transform и for_each
Анонимная лямбда функция в С++ в наиболее абстрактном виде выглядит так:
[](){}или так:
[]() mutable -> T { }
где
[] - список внешних переменных передаваемых внутрь лямбда функции;
() - список аргументов лямбда функции;
T - явно задаваемый тип возвращаемой лямбда функцией значения;
{} - тело лямбда функции.
Рассмотрим простой пример использования алгоритмов for_each и transform:
#include <algorithm>
#include <vector>
#include <iostream>
class functorType1{
public:
void operator()(double i){
std::cout << i << std::endl;
}
};
class functorType2{
public:
double operator()(double i){
return ++i;
}
};
int main(int argc, char* argv[]){
std::vector<double> v;
functorType1 functorObject1;
functorType2 functorObject2;
v.push_back(1);
v.push_back(2);
v.push_back(3);
std::for_each(v.begin(), v.end(), functorObject1);
std::transform(v.begin(), v.end(), v.begin(), functorObject2);
std::for_each(v.begin(), v.end(), functorObject1);
return 0;
}
А теперь то же самое, но с использованием лямбда выражения (они обозначены жирным шрифтом):
#include <algorithm>
#include <vector>
#include <iostream>
int main(int argc, char* argv[]){
std::vector<double> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
std::for_each(v.begin(), v.end(), [](double i){std::cout << i << std::endl;});
std::transform(v.begin(), v.end(), v.begin(), [](double i) ->double {return ++i;});
std::for_each(v.begin(), v.end(), [](double i){std::cout << i << std::endl;});
return 0;
}
Это более удобно для использования маленькой функции. Не нужно ее определять где-то. Используется прямо на месте. Получается более удобно читаемый код.
Теперь чуть модифицируем этот код для иллюстрации использования внешних к лямбда функции переменных:
#include <algorithm>
#include <vector>
#include <iostream>
int main(int argc, char* argv[]){
double var1=10;
double var2=100;
std::vector<double> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
std::for_each(v.begin(), v.end(), [](double i){std::cout << i << std::endl;});
std::transform(v.begin(), v.end(), v.begin(), [var1, var2](double i) ->double {return ++i/var1*var2;});
std::for_each(v.begin(), v.end(), [](double i){std::cout << i << std::endl;});
return 0;
}
Все примеры компилировались командой g++ ourSample.cpp -std=c++11на системе Дебиан.
суббота, 3 января 2015 г.
Строковые типы в Windows, часть 2
Если мы работаем со строками STL в Windows и хотим быть независимыми от значения переменной _UNICODE (то есть писать код независимый от того работаем ли мы со строками UNICODE или нет), то тогда можно воспользоваться таким куском кода:
#ifdef _UNICODE
#define tstring wstring
#else
#define tstring string
#endif
Если воспользоваться фактом, что std::string и
std::wstring являются typedef шаблона класса std::basic_string, то можно сделать так:
namespace std
{
typedef basic_string<TCHAR>tstring;
}
Наиболее общее решение выглядит так:
#includeВзято отсюда.<tchar.h>
#include<string>
#include<fstream>
#include<sstream>
namespace std
{
typedef basic_string<TCHAR>tstring;
typedef basic_ostream<TCHAR>tostream;
typedef basic_istream<TCHAR>tistream;
typedef basic_iostream<TCHAR>tiostream;
typedef basic_ifstream<TCHAR>tifstream;
typedef basic_ofstream<TCHAR>tofstream;
typedef basic_fstream<TCHAR>tfstream;
typedef basic_stringstream<TCHAR>tstringstream;
}
Подписаться на:
Сообщения (Atom)
