Русский
Русский
English
Статистика
Реклама

Лайфхаки для гиков

Перевод Шесть пасхалок GitHub

31.03.2021 18:20:59 | Автор: admin
В недрах кода GitHub скрыто немало пасхалок. Здесь мы поговорим о некоторых из них.



Кстати, вы знали о том, что фразу Easter egg (пасхальное яйцо, в просторечии пасхалка) придумал в 1979 году Стив Райт директор по разработке программного обеспечения Atari? Если вы смотрели фильм Первому игроку приготовиться значит вам всё уже должно быть понятно. Вот фрагмент фильма, где игрок находит первую в мире пасхалку, скрытую в классической игре Adventure.

1. Просто число


Полагаю, не существует такого языка программирования, в стандартной или математической библиотеке которого нет константы, хранящей значение числа . Но если случилось так, что поисковик Google упал, а то, чему учили на занятиях по математике, вылетело из головы, вспомнить значение числа можно, просто перейдя по адресу https://github.com/.

Откроется страница, на которой, в стиле ASCII-арта, будет показано число , записанное с точностью до 336 знака после запятой. Это очень удобно.


Число

Насколько я знаю, число , представленное другими способами, можно обнаружить, добавив к вышеприведённому адресу расширения файлов наподобие .json и .jpeg.


Вкусное число

2. Октокоты


Продолжим тему ASCII-арта. Знали ли вы о том, что в API GitHub есть конечная точка, ведущая к ASCII-изображению октокота Моны логотипа GitHub. Для того чтобы это изображение увидеть, нужно открыть в браузере адрес https://api.github.com/octocat (или воспользоваться curl).


Октокот

Облачко с текстом содержит частицу дзен-мудрости GitHub. Подробности об этом можно почитать здесь.

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

3. Всё есть дзен


Тот, кто весь долгий рабочий день глядит в тёмное окно терминала, пользуясь GitHub CLI, может позволить себе прогулку по дзен-саду своего репозитория, напоминающую старую текстовую игру. Для этого достаточно воспользоваться командой gh repo garden. По этому саду можно, в полном смысле этого слова, прогуляться, пользуясь навигационными клавишами, применяемыми в vi.

image

Дзен-сад

Каждый цветок в этом саду представлен первой буквой GitHub-имени пользователя, сделавшего коммит. Цвет цветка это первые 6 символов SHA-хеша коммита, воспринятых системой как шестнадцатеричный код цвета.

В результате, например, коммит b6b3d26ee50fc6540e1796d8bdc563d22da44ba5 будет представлен весьма приятным оттенком сиреневого цвета #b6b3d2.

4. Приукрашенные профили пользователей


То, о чём тут пойдёт речь, не такая уж и пасхалка. Это, скорее, неочевидная полезная возможность системы. Заключается она в добавлении в свой аккаунт репозитория, название которого совпадает с именем пользователя.

image

Особый репозиторий

Поместив в этот репозиторий немного Markdown-текста и пару картинок, можно рассказать о себе, о своих проектах, или о чём угодно другом.

Если вы хотите оснастить свой профиль интересным файлом README и ищете источник вдохновения взгляните на этот материал, где рассматривается десять достойных внимания примеров подобных файлов.

5. Жуть на панели Contributions


Раз в год панель Contributions выглядит гораздо страшнее, чем обычно. Для её раскрашивания, вместо оттенков зелёного цвета используются варианты цвета хэллоуинского (есть ведь такое слово?).


Хэллоуинская панель Contributions

6. Просмотр панели Contributions в стиле игр 1980-х


GitHub Skyline это, если кто не знает, инструмент для создания симпатичных трёхмерных визуализаций активности пользователя за указанный год. Вот, например, моя активность в 2020 году. То, что формирует GitHub Skyline, можно скачать в виде .stl-файла и напечатать на 3D-принтере (или заказать печать). Можно исследовать то, что получилось, в виртуальной реальности.

image

GitHub Skyline

А вот для того чтобы найти в GitHub Skyline пасхалку понадобится ввести код Konami ( B A). Тогда включится машина времени, которая унесёт вас далеко в прошлое. Вот твит того, кто нашёл эту интересную штуку.

Знаете какие-нибудь пасхалки в популярных сервисах вроде GitHub?
Подробнее..

50 оттенков жёлтого. Часть 2

03.04.2021 16:09:23 | Автор: admin
Продолжим подкреплять теорию практикой. В первой части статьи я рассказал о своих ранних экспериментах по отбеливанию пластмассы успешных и не очень. Несмотря на большой объём материала, там, по сути, был рассмотрен лишь один вариант с использованием жидкой перекиси водорода и солнечного света. И хотя результаты получились обнадёживающие, у описанного метода есть масса ограничений.




Сегодня мы поговорим о том, как эти ограничения преодолеть.

Глава четвёртая. Мы не можем ждать милостей от природы!


А что, у вас солнца совсем не бывает?
Бывает, но я в тот день болел

Полагаться на такой редкий в наших краях ресурс, как солнце, было бы недальновидно. Следующая партия пожелтевших деталей появилась у меня глубокой осенью, когда солнце стало низким и тусклым, и эффективность отбеливания упала почти до нуля. Да и в любом случае хотелось иметь полный контроль над процессом и не зависеть от внешних условий. А значит, нужно было обзавестись искусственными источниками УФ-излучения.

Поначалу я думал, что для этого необходимы лампы, дающие жёсткий ультрафиолет (типа бактерицидных). Но из роликов 8 bit Guy и других энтузиастов я узнал, что работают и самые простые светодиодные ленты и прожекторы вроде тех, что используют на дискотеках. Мой выбор пал на светодиодный прожектор Anjoet с Aliexpress.


10-ваттный Светильник выпускного вечера обошёлся мне примерно в 1300 рублей

В пару к холодному полупроводниковому источнику света было решено также купить тёплый ламповый (да простят меня за эксплуатацию этого набившего оскомину мема). Им стал Camelion FT8-18W Blacklight Blue G13.


Помимо собственно люминесцентной лампы понадобится также плафон с блоком питания

Для лампы Camelion заявлена длина волны 365 нм, а для прожектора Anjoet и вовсе 395. Это очень близко к диапазону видимого света (от 400 нм), так что у меня были большие сомнения в эффективности ламп.
Внимание! Яркий ультрафиолет, даже из ближнего диапазона, совсем не полезен для глаз. Выключайте лампы, когда находитесь рядом, либо используйте защитные очки.

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



За исключением источника ультрафиолета, всё осталось как и в прошлых опытах: 15-процентная перекись водорода в полиэтиленовом пакете. Самым удобным местом для проведения эксперимента оказалась ванная. Легко закрепить лампу, есть розетка, не страшно пролить перекись, да и синий свет никому не мешает.


Баланс белого на камере сходит с ума

А что до невозможности пользоваться ванной по прямому назначению тут остаётся разве что вспомнить классику с Баша.
xxx: знал я одного чувака
xxx: он в 98 году купил пень на 350мгц
xxx: налил в ванну глицерина
xxx: разобрал холодильник, вынул катушки, сунул в ванну
xxx: охладил глицерин почти до нуля
xxx: положил в него комп
xxx: и разогнал до 1.3ггц
yyy: А где же он мылся тогда?
xxx: после всего что я написал ты ещё думаешь что он мылся?!

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



С ней, кстати, произошёл интересный курьёз. На этой заглушке был след, оставшийся от наклейки. Вокруг пластмасса пожелтела, но под наклейкой сохранился родной цвет. Я ещё подумал, что это хороший тестовый образец можно будет выяснить, нужно ли закрывать непожелтевшие участки маской, чтобы они не стали светлее, чем нужно.



Но после того, как я включил прожектор, в ультрафиолетовых лучах проступили таинственные письмена!


Мене, мене, текел, упарсин

Интересно, сколько лет потребовалось на экспонирование этой фотографии? Уже давно нет ни наклейки, ни железа, о котором она сообщала, а корпус по-прежнему уверен, что внутри у него стоит процессор Intel.
После стольких лет?
Всегда.

В общем, я оставил обе детальки в своём антисолярии на ночь. Но когда я утром извлёк их из пакета, то почти никакого эффекта не обнаружилось. Это было фиаско. Если даже люминесцентная лампа, дающая, по идее, более глубокий ультрафиолет, не сработала, то стоит ли чего-то ждать от светодиодного прожектора? Но не зря же я его покупал нужно попробовать.



И, к моему огромному удивлению, уже через пару часов рамка заметно побелела! А ещё через четыре часа её цвет восстановился полностью.


В сравнении с образцовой деталью. Трещина в углу рамки появилась задолго до моих опытов

Не знаю, с чем связана такая разница в эффективности ламп. Субъективно свет от них кажется одинаково ярким. Но факт остаётся фактом, так что я поспешил заказать у китайцев ещё один такой прожектор.

Глава пятая. Купаться запрещено!



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

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

  • 500 мл перекиси водорода с концентрацией от 10 до 15%;
  • 2 столовых ложки с горкой ксантановой камеди;
  • 1 чайная ложка глицерина;
  • 1/4 чайной ложки усилителя для стирки Oxy.

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

Для нужд парикмахеров выпускается осветляющий гель на основе всё той же перекиси водорода, который называют оксигентом. Он идеально подходит для наших целей: концентрация от 3 до 12% и оптимальная густота, которая позволяет его легко наносить, но не даёт ему стекать с поверхности. Я использовал 12-процентный гель от фирмы Estel, но наверняка сгодится и любой другой.


Литровая бутыль стоит около 400 рублей

В применении гелеобразного состава есть своя специфика. Нужно следить за тем, чтобы он был нанесён без пропусков и как можно более равномерным слоем. Если просто оставить его на воздухе, он быстро высохнет, что приведёт к массе проблем, так что вашим лучшим другом на время опытов с отбеливанием должна стать полиэтиленовая плёнка. Укрывая детали плёнкой, нужно следить за тем, чтобы она не выдавила гель, иначе могут появиться пятна и полосы.

Первой на отбеливание оксигентом традиционно отправилась заглушка, и результат не заставил себя долго ждать. Ну а где заглушка, там и весь корпус! Увы, я снова не нашёл фото до отбеливания, но можете поверить мне на слово, что передняя панель была достаточно жёлтой.


Теперь пластиковая панель не отличается по цвету от порошковой краски на стенках

Убедившись, что гель работает, я взялся за более сложный случай старый сканер, который почти 20 лет стоял одним боком к окну. Легко заметить чёткую границу, проходящую вдоль левого края.



Это очень интересный объект для эксперимента, поскольку исходный цвет пластмассы далёк от белого. Те, кто читал предыдущую часть статьи, помнят, что там я спорил с тезисом, будто перекись лишь осветляет пластмассу. Я придерживаюсь мнения, что она в первую очередь именно убирает желтизну, а эффект осветления выражен куда слабее. Так что будет лишняя возможность проверить, кто прав.


Сравнение боковин для наглядности

Я надел хозяйственные перчатки и щедро обмазал край сканера гелем. Малярный скотч выполняет двойную функцию уменьшает воздействие на менее пожелтевшие участки и не даёт гелю затечь в щель между пластмассой и стеклом.



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

Ну а теперь включаем прожекторы (к этому моменту их стало два), и в ванной начинается аквадискотека.


Старый штатив для фотоаппарата прекрасно подошёл на роль держателя

Через шесть часов я стёр гель и увидел под ним искомый серо-синий цвет.


Похоже, что боковины больше не различаются по цвету

У геля есть такая особенность, что после его снятия пластмасса выглядит будто бы немного влажной. Примерно через полчаса этот эффект уходит, и она приобретает тот цвет, который останется надолго. Отбеливание получилось не на 100% равномерным, но чтобы заметить это, нужно сильно приглядываться.


Как я и предполагал, гель убрал желтизну, а не просто осветлил пластик

Ну что ж, метод дважды доказал свою работоспособность. Так не замахнуться ли нам на что-нибудь более масштабное? Мне давно мозолила глаза пожелтевшая панель на стиральной машинке. Она стоит на кухне возле окна, а окно выходит на южную сторону. В итоге за пять лет на панели образовалось заметное пятно.


Кювета явно сделана из другой пластмассы, поскольку пожелтела значительно меньше

Поначалу я нанёс гель только на сильно повреждённый участок основной панели.


Снимки на телефон лучше передают атмосферу

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


Результат в наглядном сравнении

Не скажу, что желтизна ушла полностью, но разница очевидна.

Выводы кратко:


  1. Светодиодные ультрафиолетовые прожекторы хорошо подходят для отбеливания, а вот эффективность люминесцентных ламп под вопросом.
  2. Парикмахерский гель для осветления волос эффективен, но требует аккуратности в использовании.
  3. Гель обязательно нужно накрывать плёнкой. Рекомендуется также периодически его помешивать и разгонять пузырьки.
  4. Лучше покрывать гелем всю деталь целиком, даже если она пожелтела не везде. Белее белого вы пластмассу всё равно не сделаете, а вот если получится ступенька, не факт, что от неё удастся легко избавиться.
  5. Если ступенька всё же появилась, не пытайтесь исправить её, нанося гель только на более жёлтую часть. Скорее всего, в результате у вас будет две ступеньки. Покрывайте всю деталь.

В этой статье я рассказал не обо всех своих опытах, но в противном случае её объём вышел бы совсем запредельным. В дальнейшем я планирую отточить метод и собрать что-то вроде установки для отбеливания, которая давала бы предсказуемый результат для деталей любого размера, которые только можно встретить в компьютерной технике. Так что, вполне возможно, когда-нибудь вы увидите и третью часть этого материала.

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

Подробнее..

Перевод Программирование голосом. Передовые рубежи разработки ПО

06.04.2021 12:11:10 | Автор: admin

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


Работа в Serenade

Технологическая основа


Мы все больше и больше взаимодействуем с гаджетами через речь. Наши старые виртуальные помощники вроде Alexa и Siri теперь объединяются с автомобильными ассистентами, например Apple CarPlay и Android Auto, а также с приложениями, работающими с голосовой биометрикой и командами. Но что, если саму технологию можно было бы создавать при помощи голоса?

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

Однако программирование голосом оказывается не столь простым и кроет в себе несколько слоев сложной технологии. К примеру, в Serenade используется движок преобразования речи в текст, созданный специально для работы с кодом, в отличие от аналогичного API Speech-to-text, спроектированного Google для разговорной речи. После того, как инженер проговаривает код, движок Serenade передает его в слой обработки естественного языка, в котором специально обученные модели машинного обучения (МО) распознают и переводят стандартные программные конструкции в синтаксически верный код.

Существует две основных платформы, предлагающих различные подходы к задачам рецитирования кода компьютеру. Одна из них, Serenade, выступает в качестве цифрового помощника, позволяя описывать вводимые в коде команды без необходимости проговаривать каждую инструкцию дословно. Другой инструмент, Talon, предоставляет более тонкий контроль над каждой строкой, что также требует более тщательного понимания каждой программируемой в машину задачи. Ниже вы видите простой пример пошагового руководства в Serenade и Talon по генерации кода Python, выводящего на экран слово hello.




Технология против офисного синдрома


Компания Serenade, собравшая $2.1 миллиона на этапе начального финансирования в 2020 году, родилась в силу необходимости, после того, как одному из ее основателей, Мэтту Уитхоффу, в 2019 году бы поставлен диагноз хроническая травма от повторяющегося напряжения. Я бросил работу разработчиком ПО в Quora, потому что просто перестал с ней справляться, говорит Мэтт. В качестве альтернативы можно было заняться деятельностью, не требующей такого количества набора текста, либо искать другой выход.

Тем же путем в 2017 году пошел Райан Хайлман, оставив свое постоянное место работы программистом, после того как годом ранее у него возникли сильные боли в руке. Тогда Тайлман занялся разработкой Talon, платформы для написания кода без использования рук. Он говорил: Задача Talon полностью заменить клавиатуру и мышь для любого человека.

С этой целью в ней реализовано три программных компонента: распознавание речи, отслеживание глаз и распознавание звука. Движок распознавания речи основан на разработанной Facebook автоматической системе Wav2letter, которую Тайлман расширил командами для программирования. При этом функция отслеживания глаз и распознавания звука симулирует управление с помощью мыши. Курсор перемещается по экрану вслед за перемещением взгляда, а клики совершаются в ответ на издаваемый ртом звук, напоминающий откупоривание шампанского. Как говорит Райан: Издать такой звук легко. Он не требует особых усилий и распознается очень быстро, что представляет более быстрый невербальный способ реализации щелчков мыши, не вызывающий голосового напряжения.

Написание кода с помощью Talon звучит подобно инопланетному языку, как это продемонстрировала Эмили Ши, инженер и практик данной техники, выступавшая на конференции в 2019 году. Предложенное ей видео наполнено командами типа slap (Ввод), undo, spring 3 (перейти к третьей строке файла) и phrase name op equals snake extract word paren mad (дает такую строку: name = extract_word(m)).

С другой стороны, при написании кода с помощью Serenade, команды проговариваются более естественным образом. Можно сказать delete import, чтобы удалить инструкцию импорта в начале файла или build, чтобы выполнить пользовательскую команду сборки. Также можно сказать add function factorial для создания функции, вычисляющей факториал, например, в JavaScript. В этом случае приложение полностью возьмет на себя синтаксис, включая ключевое слово function, скобки и фигурные скобки, избавив вас от необходимости явно проговаривать каждый элемент.

Для программирования голосом требуется хороший микрофон, особенно если вы хотите устранить фоновый шум. Тем не менее модели Serenade обучены на аудио, получаемом с микрофонов ноутбуков. Если же вы хотите использовать Talon с функцией отслеживания движения глаз, то также потребуется соответствующее оборудование. Хотя Talon отлично работает и без него. Открытые платформы для написания кода голосом, такие как Aenea и Caster, хоть и бесплатны, но обе опираются на движок распознавания речи Dragon, который пользователь должен приобретать отдельно. При этом Caster предлагает поддержку Kaldi, открытого набора инструментов для распознавания речи, а также Windows Speech Recognition, поставляемого с ОС Windows по умолчанию.

По словам сооснователя Serenade Labs, Томми МакУилльям, результаты говорят сами за себя: Описать желаемое действие становится намного проще. Ведь куда легче просто сказать move these three lines down или duplicate this method вместо того, чтобы печатать все эти инстуркции или даже использовать горячие клавиши.

Программирование голосом также позволяет людям с травмами или хроническими болями продолжить свою карьеру. Как говорит Эмили: Способность использовать голос, исключая из процесса участие рук, открыла для меня гораздо более широкий спектр возможностей взаимодействия с компьютером.

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

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

Подробнее..

Валидация UTF-8 меньше чем за одну инструкцию на байт

06.04.2021 16:12:32 | Автор: admin


Даниэль Лемир профессор Заочного квебекского университета (TLUQ), придумавший способ очень быстро парсить double совместно с инженером Джоном Кайзером из Microsoft опубликовали ещё одну свою находку: валидатор UTF-8, обгоняющий библиотеку UTF-8 CPP (2006) в 48..77 раз, ДКА от Бьёрна Хёрманна (2009) в 20..45 раз, и алгоритм Google Fuchsia (2020) в 13..35 раз. Новость об этой публикации на хабре уже постили, но без технических подробностей; так что восполняем этот недочёт.

Требования UTF-8


Для начала вспомним, что Unicode допускает code points от U+0000 до U+10FFFF, которые кодируются в UTF-8 последовательностями от 1 до 4 байтов:

Число байтов в кодировке Число битов в code point Минимальное значение Максимальное значение
1 1..7 U+0000 = 00000000 U+007F = 01111111
2 8..11 U+0080 = 11000010 10000000 U+07FF = 11011111 10111111
3 12..16 U+0800 = 11100000 10100000 10000000 U+FFFF = 11101111 10111111 10111111
4 17..21 U+010000 = 11110000 10010000 10000000 10000000 U+10FFFF = 11110100 10001111 10111111 10111111

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

Какого рода ошибки могут быть в строке, закодированной таким образом?

  1. Незаконченная последовательность: на месте, где ожидался продолжающий байт, встретился ведущий байт или ASCII-символ;
  2. Неначатая последовательность: на месте, где ожидался ведущий байт или ASCII-символ, встретился продолжающий байт;
  3. Слишком длинная последовательность: ведущий байт 11111xxx соответствует пятибайтной или более длинной последовательности, запрещённой в UTF-8;
  4. Выход за границы Unicode: после расшифровки четырёхбайтной последовательности получился code point выше U+10FFFF.

Если в строке нет ни одной из этих четырёх ошибок, то её можно расшифровать в последовательность корректных code points. UTF-8, однако, требует большего чтобы каждая последовательность корректных code points кодировалась единственным образом. Это добавляет ещё два рода возможных ошибок:

  1. Неминимальная последовательность: для расшифрованного code point возможна более короткая кодировка;
  2. Суррогаты: code points в диапазоне от U+D800 до U+DFFF зарезервированы для UTF-16, и последовательность из двух таких суррогатов обозначает code point выше U+FFFF. UTF-8 требует, чтобы такие code points кодировались напрямую, а не как пары суррогатов.

В редко используемой кодировке CESU-8 последнее требование отменено (а в MUTF-8 ещё и предпоследнее), благодаря чему длина последовательности ограничена тремя байтами, но расшифровка и валидация строк усложняются. Например, смайлик U+1F600 GRINNING FACE представляется в UTF-16 парой суррогатов 0xD83D 0xDE00, и CESU-8/MUTF-8 переводят её в пару трёхбайтных последовательностей 0xED 0xA0 0xBD 0xED 0xB8 0x80; но в UTF-8 этот смайлик кодируется одной четырёхбайтной последовательностью 0xF0 0x9F 0x98 0x80.

Для каждого рода ошибки ниже перечислены последовательности битов, которые к ней приводят:
Незаконченная последовательность Недостаёт 2-ого байта 11xxxxxx 0xxxxxxx
11xxxxxx 11xxxxxx
Недостаёт 3-его байта 111xxxxx 10xxxxxx 0xxxxxxx
111xxxxx 10xxxxxx 11xxxxxx
Недостаёт 4-ого байта 1111xxxx 10xxxxxx 10xxxxxx 0xxxxxxx
1111xxxx 10xxxxxx 10xxxxxx 11xxxxxx
Неначатая последовательность Лишний 2-ой байт 0xxxxxxx 10xxxxxx
Лишний 3-ий байт 110xxxxx 10xxxxxx 10xxxxxx
Лишний 4-ый байт 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx
Лишний 5-ый байт 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
Слишком длинная последовательность 11111xxx
Выход за границы Unicode U+110000..U+13FFFF 11110100 1001xxxx
11110100 101xxxxx
U+140000 11110101
1111011x
Неминимальная последовательность 2-байтная 1100000x
3-байтная 11100000 100xxxxx
4-байтная 11110000 1000xxxx
Суррогаты 11101101 101xxxxx


Валидация UTF-8


При наивном подходе, использованном в библиотеке UTF-8 CPP серба Неманьи Трифуновича, валидация выполняется каскадом вложенных ветвлений:

const octet_difference_type length = utf8::internal::sequence_length(it);// Get trail octets and calculate the code pointutf_error err = UTF8_OK;switch (length) {    case 0:        return INVALID_LEAD;    case 1:        err = utf8::internal::get_sequence_1(it, end, cp);        break;    case 2:        err = utf8::internal::get_sequence_2(it, end, cp);    break;    case 3:        err = utf8::internal::get_sequence_3(it, end, cp);    break;    case 4:        err = utf8::internal::get_sequence_4(it, end, cp);    break;}if (err == UTF8_OK) {    // Decoding succeeded. Now, security checks...    if (utf8::internal::is_code_point_valid(cp)) {        if (!utf8::internal::is_overlong_sequence(cp, length)){            // Passed! Return here.

Внутри sequence_length() и is_overlong_sequence() тоже ветвления в зависимости от длины последовательности. Если во входной строке непредсказуемо чередуются последовательности разной длины, то предсказатель переходов не сможет избежать сброса конвеера по нескольку раз на каждом обрабатываемом символе.

Более эффективный подход к валидации UTF-8 заключается в использовании конечного автомата из 9 состояний: (состояние ошибки на диаграмме не показано)



Когда таблица переходов автомата составлена, то код валидатора получается очень простым:

uint32_t type = utf8d[byte];*codep = (*state != UTF8_ACCEPT) ?  (byte & 0x3fu) | (*codep << 6) :  (0xff >> type) & (byte);*state = utf8d[256 + *state + type];

Здесь для каждого обрабатываемого символа повторяются одни и те же действия, без условных переходов поэтому сбросов конвеера не потребуется; с другой стороны, на каждой итерации осуществляется дополнительный доступ к памяти (к таблице переходов utf8d) впридачу ко чтению входного символа.

Лемир и Кайзер взяли за основу своего валидатора этот же ДКА, и достигли ускорения в десятки раз за счёт применения трёх усовершенствований:

  1. Таблицу переходов удалось ужать с 364 байтов до 48, так что она целиком помещается в трёх векторных регистрах (по 128 бит), и обращения к памяти требуются только для чтения входных символов;
  2. Блоки по 16 соседних байтов обрабатываются параллельно;
  3. Если 16-байтный блок целиком состоит из ASCII-символов то он заведомо корректный, и нет нужды в более тщательной проверке. Этот срез пути ускоряет обработку реалистичных текстов, содержащих целые предложения латиницей, в два-три раза; но на случайных текстах, где латиница, иероглифы и смайлики равномерно перемешаны, это ускорения не даёт.

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

Уменьшение таблицы переходов


Первое усовершенствование основывается на том наблюдении, что для обнаружения большинства ошибок (12 недопустимых последовательностей битов из 19 перечисленных в таблице выше) достаточно проверить 12 первых битов последовательности:
Незаконченная последовательность Недостаёт 2-ого байта 11xxxxxx 0xxxxxxx 0x02
11xxxxxx 11xxxxxx
Неначатая последовательность Лишний 2-ой байт 0xxxxxxx 10xxxxxx 0x01
Слишком длинная последовательность 11111xxx 1000xxxx 0x20
11111xxx 1001xxxx 0x40
11111xxx 101xxxxx
Выход за границы Unicode U+1[1235679ABDEF]xxxx 111101xx 1001xxxx
111101xx 101xxxxx
U+1[48C]xxxx 11110101 1000xxxx 0x20
1111011x 1000xxxx
Неминимальная последовательность 2-байтная 1100000x 0x04
3-байтная 11100000 100xxxxx 0x10
4-байтная 11110000 1000xxxx 0x20
Суррогаты 11101101 101xxxxx 0x08

Каждой из этих возможных ошибок исследователи присвоили один из семи битов, как показано в самом правом столбце. (Присвоенные биты различаются между их опубликованной статьёй и их кодом на GitHub; здесь взяты значения из статьи.) Для того, чтобы обойтись семью битами, два подслучая выхода за границы Unicode пришлось переразбить так, чтобы второй объединялся с 4-байтной неминимальной последовательностью; а случай слишком длинной последовательности разбит на три подслучая и объединён с подслучаями выхода за границы Unicode.

Таким образом с ДКА Хёрманна были произведены следующие изменения:

  1. Вход поступает не по байту, а по тетраде (полубайту);
  2. Автомат используется как недетерминированный обработка каждой тетрады переводит автомат между подмножествами всех возможных состояний;
  3. Восемь корректных состояний объединены в одно, зато одно ошибочное разделено на семь;
  4. Три соседние тетрады обрабатываются не последовательно, а независимо друг от друга, и результат получается как пересечение трёх множеств конечных состояний.

Благодаря этим изменениям, для описания всех возможных переходов достаточно трёх таблиц по 16 байт: каждый элемент таблицы используется как битовое поле, перечисляющее все возможные конечные состояния. Три таких элемента объединяются по AND, и если в результате есть ненулевые биты, значит, обнаружена ошибка.
Тетрада Значение Возможные ошибки Код
Старшая в первом байте 07 Лишний 2-ой байт 0x01
811 (нет) 0x00
12 Недостаёт 2-ого байта; 2-байтная неминимальная последовательность 0x06
13 Недостаёт 2-ого байта 0x02
14 Недостаёт 2-ого байта; 2-байтная неминимальная последовательность; суррогаты 0x0E
15 Недостаёт 2-ого байта; слишком длинная последовательность; выход за границы Unicode; 4-байтная неминимальная последовательность 0x62
Младшая в первом байте 0 Недостаёт 2-ого байта; лишний 2-ой байт; неминимальная последовательность 0x37
1 Недостаёт 2-ого байта; лишний 2-ой байт; 2-байтная неминимальная последовательность 0x07
23 Недостаёт 2-ого байта; лишний 2-ой байт 0x03
4 Недостаёт 2-ого байта; лишний 2-ой байт; выход за границы Unicode 0x43
57 0x63
810, 1215 Недостаёт 2-ого байта; лишний 2-ой байт; слишком длинная последовательность
11 Недостаёт 2-ого байта; лишний 2-ой байт; слишком длинная последовательность; суррогаты 0x6B
Старшая во втором байте 07, 1215 Недостаёт 2-ого байта; слишком длинная последовательность; 2-байтная неминимальная последовательность 0x06
8 Лишний 2-ой байт; слишком длинная последовательность; выход за границы Unicode; неминимальная последовательность 0x35
9 0x55
1011 Лишний 2-ой байт; слишком длинная последовательность; выход за границы Unicode; 2-байтная неминимальная последовательность; суррогаты 0x4D

Остались необработанными ещё 7 недопустимых последовательностей битов:
Незаконченная последовательность Недостаёт 3-его байта 111xxxxx 10xxxxxx 0xxxxxxx
111xxxxx 10xxxxxx 11xxxxxx
Недостаёт 4-ого байта 1111xxxx 10xxxxxx 10xxxxxx 0xxxxxxx
1111xxxx 10xxxxxx 10xxxxxx 11xxxxxx
Неначатая последовательность Лишний 3-ий байт 110xxxxx 10xxxxxx 10xxxxxx
Лишний 4-ый байт 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx
Лишний 5-ый байт 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

И здесь пригождается старший бит, предусмотрительно оставленный в таблицах переходов неиспользованным: он будет соответствовать последовательности битов 10xxxxxx 10xxxxxx, т.е. двум продолжающим байтам подряд. Теперь проверка трёх тетрад может либо обнаружить ошибку, либо дать результат 0x00 или 0x80. И вот этого результата первой проверки вместе с первой тетрадой нам уже достаточно:
Недостаёт 3-его байта 111xxxxx 10xxxxxx 0xxxxxxx 111xxxxx (0x00)
111xxxxx 10xxxxxx 11xxxxxx
Недостаёт 4-ого байта 1111xxxx 10xxxxxx 10xxxxxx 0xxxxxxx 1111xxxx (x) (0x00)
1111xxxx 10xxxxxx 10xxxxxx 11xxxxxx
Лишний 3-ий байт 110xxxxx 10xxxxxx 10xxxxxx 110xxxxx (0x80)
Лишний 4-ый байт 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx 1110xxxx (x) (0x80)
Лишний 5-ый байт 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx (x) (0x80)
Допустимые комбинации 111xxxxx (0x80)
1111xxxx (x) (0x80)

Значит, для завершения проверки достаточно убедиться, что каждый результат 0x80 соответствует одной из двух допустимых комбинаций.

Векторизация


Как обрабатывать блоки по 16 соседних байтов параллельно? Центральная идея состоит в том, чтобы использовать инструкцию pshufb как 16 одновременных подстановок в соответствии с 16-байтной таблицей. Для второй проверки нужно найти в блоке все байты вида 111xxxxx и 1111xxxx; поскольку на Intel нет беззнакового векторного сравнения, то оно заменяется вычитанием с насыщением (psubusb).

Исходники simdjson тяжеловато читаются из-за того, что весь код разбит на однострочные функции. Псевдокод всего валидатора целиком выглядит примерно так:
prev = vector(0)while !input_exhausted:    input = vector(...)    prev1 = prev<<120 | input>>8    prev2 = prev<<112 | input>>16    prev3 = prev<<104 | input>>24    # первая проверка    nibble1 = prev1.shr(4).lookup(table1)    nibble2 = prev1.and(15).lookup(table2)    nibble3 = input.shr(4).lookup(table3)    result1 = nibble1 & nibble2 & nibble3    # вторая проверка    test1 = prev2.saturating_sub(0xDF) # 111xxxxx => >0    test2 = prev3.saturating_sub(0xEF) # 1111xxxx => >0    result2 = (test1 | test2).gt(0) & vector(0x80)    # в result1 должны быть 0x80 на тех же местах, как и в result2,    # и нули на всех остальных    if result1 != result2:        return false    prev = inputreturn true

Если некорректная последовательность находится у правого края самого последнего блока, то она этим кодом не будет обнаружена. Чтобы не заморачиваться, можно дополнить входную строку нулевыми байтами так, чтобы в конце получился один полностью нулевой блок. В simdjson предпочли вместо этого реализовать особую проверку для последних байтов: для корректности строки нужно, чтобы самый последний байт был строго меньше 0xC0, предпоследний строго меньше 0xE0, и третий с конца строго меньше 0xF0.

Последнее из усовершенствований, придуманных Лемиром и Кайзером это срез пути для ASCII. Определить, что в текущем блоке есть только ASCII-символы, очень просто: input & vector(0x80) == vector(0). В этом случае достаточно убедиться, что нет некорректных последовательностей на границе prev и input, и можно переходить к следующему блоку. Эта проверка осуществляется аналогично проверке в конце входной строки; беззнаковое векторное сравнение с [..., 0xС0, 0xE0, 0xC0], которого нет на Intel, заменяется на вычисление векторного максимума (pmaxub) и его сравнение с тем же вектором.

Проверка на ASCII оказывается единственным ветвлением внутри итерации валидатора, и для успешного предсказания этого ветвления достаточно, чтобы во входной строке не чередовались блоки целиком из ASCII со блоками, содержащими не-ASCII-символы. Исследователи обнаружили, что ещё лучших результатов на реальных текстах удаётся добиться, проверяя на ASCII объединение по OR четырёх соседних блоков, и пропуская все четыре блока в случае ASCII. И действительно: можно ожидать, что если автор текста в принципе пользуется не-ASCII-символами, то они будут встречаться как минимум раз на 64 символа, чего достаточно для предсказания перехода.

Подробнее..

Пора что-то менять! Как определить ту самую токсичность в команде комментарии инженера

08.04.2021 18:23:51 | Автор: admin

Иногда ежедневная рутина несамая сложная часть будней. Если навыходе изофиса возникает чувство, что только что завершился раунд Форт Боярда, ноПаспарту ненесёт ключ отсокровищницы возможно, дело втоксичной командной культуре.

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






Герои наших статей рассказывают, что корпоративная культура заграничных компаний, например, Uber, Booking иSpotify, разительно отличаются отроссийских: влияние токсичной команды насамочувствие ипроизводительность унас, кажется, пока недооценивают.


Новлияние это есть: Гарвардская бизнес-школа провела исследование навыборке из60,000сотрудников. Оказалось, что:


  • токсичное окружение статистически значимо влияет начеловека,
  • 38% людей намеренно работали хуже, чтобы избежать критики,
  • 12% из-за грубого обращения увольнялись.


Рассказывает Елена, QAAuto


Язадумывалась, что стоит менять работу, еще после испытательного срока. Что меня возмутило: компания невыполнила, что обещала насобеседовании. Говорили, что оформят ДМС апофакту выяснилось, смоим уровнем зарплаты ДМС вообще непредусмотрен. Неточтобы ямного болела, новедь всё, что мне говорили при приёме, оказалось неправдой.


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


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



По-моему, пора думать обувольнении иискать новую работу:


  1. Если процессы вкомпании неустраивают, нотыникак неможешь повлиять наулучшение ихили продукта потому что сделать это непозволяют.
  2. Если чувствуешь, что перестал развиваться профессионально, исамому хочется чего-то большего.
  3. Если конфликты, которые случатся вкоманде, неконструктивные, адеструктивные, иособенно протекают внеявной, пассивной форме тоесть, например, они возникают из-за личной неприязни. Несходиться скем-то вомнениях это нормально, нотолько если эти расхождения касаются какой-то задачи, проблемы, илюди вместе ищут решение. Новцелом, если вкоманде угнетающая атмосфера, ябы несоветовала терпеть. Может быть лучше!





7признаков токсичного коллектива


Токсичная командная культура опасна: как минимум, потому что люди быстрее выматываютсяи, как следствие, совершают больше ошибок. Плюс токсичная культура может привести ксильному техническому долгу ипоставить весь продукт под угрозу. Идентифицируем токсиков:


  1. Нет дружеской атмосферы
    Банально, ноактуально: радыли люди работать вэтом месте? Атмосферу будет проще заметить новичку сотрудники привыкают кобстановке иперестают обращать внимание: рыбы невидят, какой мутной стала вода ваквариуме. Если, заглянув вофис, чувствуется холод, нет минимального общения, улыбок, обмена шутками похоже, что-то идёт нетак. люди неочень рады работать вэтом месте.
  2. Одержимость титулами, должностными инструкциями ииерархией
    При встрече снезнакомым человеком онвпервую очередь рассказывает про свой титул. Втоксичной среде власть для людей важнее миссии, которую они выполняют, ауспех измеряется статусом ибонусами, иужточно неуровнем доверия вкоманде.
  3. Правила везде, илюди боятся ихнарушать
    Правила важнее, чем мнение коллег: даже если оно основано намноголетнем опыте или погружении вконтекст. Формальность рулит, илюди боятся попасть внеприятности из-за нарушения правил. Поэтому никто невысовывается.
  4. Менеджмент против сотрудников
    Ещё чуть-чуть, истенка настенку: руководство исотрудники чётко разделены надве группы иредко взаимодействуют между собой. Аесли взаимодействуют, тообщаются водностороннем порядке: диалога нет.
  5. Фокус наслабых местах инедостатках
    О нарушениях, промахах ипровалах говорят очень много, аопобедах, достижениях мало. Победы непризнают, фидбэка мало.
  6. Нет диалога
    Невыполнимые цели, предлагают нелепые планы или откровенно глупые идеи непринято обсуждать, они воспринимаются как данность исотрудники пассивно наних соглашаются. Апозже жалуются вузком кругу наихглупость.
  7. Свободы действий при выполнении работы нет
    Процедура прописана для всех иочень чётко. Если людей вообще зачто-то хвалят, тозасоблюдение инструкций, анезановые идеи. Предложить изменения значит стать нашаг ближе кувольнению.

Понять, что команда тебе подходит, невсегда получается сразу. Ябы для начала советовала просто нетерпеть инедоводить дотого состояния, вкотором оказалась сама. Это была какая-то ловушка: инастаром месте работать нет сил, именять работу опасалась. Ведь вновой компании хочется быть продуктивным, показать себя как классного специалиста аэто сложно сделать, когда выгорел впредыдущем месте. Поэтому мне было немного страшно начинать.


Втомже Гарвардском исследовании говорится, что токсичная команда влияет напроизводительность отдельно взятых сотрудников:


  • 80% людей опасались токсичности состороны коллег итратили рабочее время напереживания,
  • у66% заявили, что ихпроизводительность снизилась.

Токсичное окружение тема, которую можно обсуждать иподнимать. Ноповлиять наситуацию может только руководство, водиночку поменять уклад всей команды неполучится.


Ноглавное неотчаиваться! Когда яначала подбирать вакансии, оказалось, есть много компаний, где клюдям относятся нормально. Яснова вспомнила отом, как это классно, быть вкомпании людей, которые вместе работают над одной большой миссией, скоторыми можно расти, как профессионал ипоболтать после работы приятно тоже. Это очень воодушевило, язаново загорелась идеей найти комфортное для себя место.


Когда яприсматривала себе новую работу, изначально, конечно, фильтровала поязыкам ивыбирала продуктовые компании свой продукт приятнее развивать.


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


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


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


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


Думаете менять работу? Вботе @g_jobbot можно выложить своё резюме ипощупать рынок: проверить, какую зарплату может получать специалист свашим опытом. Это бесплатно: бот подберёт вакансии ипришлёт вТелеграм.
Подробнее..

Перевод Как параллельные вычисления повлияют на индустрию безопасности?

13.04.2021 20:10:28 | Автор: admin

У центральных и графических процессоров разная архитектура и разные сценарии использования. ЦП это мозг большинства наших электронных устройств. Они хорошо справляются с множеством различных задач. Это процессоры очень общего назначения, координирующие широкий спектр задач, которые выполняет компьютер. С другой стороны, графические процессоры гораздо более специализированные вычислительные системы. Они предназначены для эффективной обработки 3D-изображений, но визуализация графики это очень большая вычислительная нагрузка на матричную арифметику. Типы вычислений, в которых графическим процессорам нет равных, называются параллельными вычислениями, то есть это задачи, которые можно разделить на меньшие, независимые вычисления и выполнять одновременно. И этому потенциалу находится нетипичное применение.


В этом 90-секундном видео, где разрушители мифов Адам Сэвидж и Джейми Хайнеман показывают робота-художника, которого они построили, чтобы проиллюстрировать работу параллельных вычислений.

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

Если посмотреть на то, как количество ядер в графическом процессоре меняется со временем, видно, что последние несколько лет оно растёт экспоненциально. И в то время как большинство центральных процессоров имеет несколько десятков ядер, графические процессоры насчитывают тысячи ядер. В новейших высокопроизводительных графических процессорах компании Nvidia более 10 000 ядер.

Этот беспрецедентный рост привёл к тому, что разработчики начали изучать возможности применения графических процессоров не только для графической обработки, но и для того, что теперь известно как неспециализированные вычисления на графических процессорах (GPGPU).

Чтобы помочь разработчикам использовать все возможности графических процессоров и позволить центральным и графическим процессорам обрабатывать данные в двух направлениях, компания Nvidia создала программную платформу CUDA, которая облегчает разработчикам создание приложений с использованием API.

Они всегда сотрудничают с разработчиками в целях реструктуризации алгоритмов, используемых в их приложениях, чтобы использовать аппаратное обеспечение Nvidia с максимальной отдачей. В результате достигнута очень хорошая интеграция с широко используемыми приложениями, такими как Adobe Photoshop CC, Adobe Premiere CC и Autodesk Maya.

Платформу CUDA можно скачать бесплатно, но для работы с ней требуется графический процессор Nvidia. Также существует альтернатива с открытым исходным кодом OpenCL, которая служит основной платформой для обработки графики на графических процессорах AMD. Компания Nvidia поддерживает OpenCL, но, так как платформа CUDA разрабатывается для работы с оборудованием Nvidia, она показывает более высокую производительность при работе на графических процессорах Nvidia.

Эти платформы позволяют разработчикам широко использовать графические процессоры не только для графической обработки, но и в приложениях, в которых очень выгодно применять параллельные вычисления, и взлом паролей одно из них. Взлом паролей относится к задачам, которые мы называем чрезвычайно параллельными задачами. Чрезвычайно параллельная задача это задача, которую можно тривиально разбить на более мелкие части, при этом вычисления каждой части не зависят от результатов соседей.

Рассмотрим сценарий, в котором требуется вручную сложить две матрицы 20x20. Вы зовёте ещё 19 друзей и говорите им, что каждый из них отвечает за вычисление одной строки, а затем вы снова объединяете результаты в одну матрицу.

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

Взлом паролей это чрезвычайно параллельная задача, так как он основан на том же принципе. Я уже подробно описывал взлом паролей, но сейчас хочу описать это простыми словами.

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

Для простоты предположим, что:

  • Им известно, что приложение ограничивает пароли пользователей 10 символами.

  • Они могут только попытаться перебрать пароли (предположим, что нет словаря, нет масок и нет радужных таблиц).

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

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

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

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

У параллельных вычислений много других применений, многие из которых чрезвычайно ценны для общества, например прогноз погоды для сельского хозяйства, общественный транспорт и выявление спама.

Вот почему Nvidia и другие производители вкладывали значительные средства в эту область в течение последнего десятилетия, а эффект постепенного стимулирования этих достижений будет продолжать влиять на взлом паролей.

FPGA и ASIC

Увеличение скорости хэширования в 100 раз с помощью графических процессоров плохая новость для людей, которые пытаются надёжно хранить пароли.

Однако не все алгоритмы хэширования уязвимы для атак с ускорением на основе графических процессоров.

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

bcrypt один из таких алгоритмов.

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

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

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

С другой стороны, ASIC, или интегральные микросхемы специального назначения, это фиксированные интегральные схемы для специализированного применения. Данное аппаратное обеспечение разработано в расчёте на одно применение и не может делать ничего другого, но то, для чего разработано, оно делает очень хорошо.

Графические процессоры фактически служат примером специализированных ASIC-микросхем. Вначале они были созданы строго для вычислений при решении задач визуализации. Только через некоторое время, в конце 2000-х, когда вышла платформа CUDA, они начали становиться более программируемыми.

Обратная сторона заключается в том, что разработка заказных микросхем обходится дорого, так как помимо производственных затрат требуются затраты на исследования и разработку.

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

Вот почему вы, вероятно, слышали о ASIC-микросхемах для майнинга биткойнов. Эти микросхемы могут делать только одно вычислять двойные хэши SHA256, а в настоящее время майнинг биткоинов достаточно прибылен, чтобы оправдать их производство.

В начале 2010-х годов ASIC-микросхемы стали де-факто стандартным оборудованием установок для майнинга биткойнов, свергнув с трона кластеры из нескольких высококлассных графических процессоров, потому что они в этом деле были гораздо эффективнее.

Можно ли ASIC-микросхемы вместо майнинга биткоинов использовать взлома паролей?

Как я уже сказал, ASIC-микросхемы разрабатываются с нуля с одной целью, и в случае установок для майнинга биткойнов эта задача заключается в вычислении двойных хэшей SHA256.

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

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

Злоумышленникам потребовалось бы настроить по одной ASIC-установке для каждой функции хэширования и настраиваемой функции, такой как bcrypt, для каждой вероятной комбинации параметров. Мало того, что это трудно сделать с точки зрения разработки, но атака также должна иметь смысл с финансовой точки зрения.

FPGA-установки для взлома Bcrypt-паролей

Несмотря на то что FPGA менее эффективны, чем ASIC, для специализированного применения, такого как вычисление хэшей по определенному алгоритму, они компенсируют это большей дешевизной и универсальностью.

Давайте посмотрим, как FPGA смогут преодолеть ограничения графических процессоров при взломе bcrypt.

С общими функциями хэширования, такими как SHA1 и MD5, вероятно, придётся попрощаться из-за графических процессоров, так как эти алгоритмы не создают узкие места в памяти, поскольку они не были предназначены для хранения паролей.

Для вычисления bcrypt-хэша процессору придётся постоянно обращаться к инструкциям, хранящимся в памяти. У каждого ядра есть быстрый, но небольшой объём памяти (кэш L1). Если в памяти L1 недостаточно места для вычисления хэша, данные должны храниться в более медленной основной оперативной памяти графического процессора, общей для всех ядер.

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

Это не проблема для FPGA-микросхем, потому что у них более чем достаточно памяти L1 для работы с bcrypt-хэшами.

Персонал службы уведомлений о нарушении паролей Scattered Secrets хотел проверить это, поэтому они построили кластер из FPGA-микросхем, способный взламывать bcrypt примерно в 3540 раз быстрее, чем современные высокопроизводительные графические процессоры, используя только около 5% мощности.

Используя RTX 2080Ti в качестве бенчмарка, они получили 54 тысячи bcrypt-хэшей в секунду на своей тестовой установке, в то время как установка, которую они построили с 18 четырёхъядерными FPGA-платами Spartan-6 LX150, выдавала 2,1 миллиона bcrypt-хэшей в секунду.

Имейте в виду, что это не самые современные FPGA-микросхемы: они были введены ещё в 2011 году. Эти платы были популярным инструментом, потому что они поддерживали Jack The Ripper, популярное программное обеспечение для взлома паролей. Поскольку приложения для взлома паролей начинают поддерживать новые микросхемы, скорость таких атак будет только увеличиваться.

Заглядывая в будущее

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

Всегда будут существовать финансовые стимулы разработки новых технологий для решения сложных проблем, с которыми мы сталкиваемся как общество. Число ядер в одном графическом процессоре выросло с 1 ядра в 1995 году до 24 ядер в 2006 году, затем подскочило до 128 ядер в 2009 году и продолжило расти экспоненциально до 10 000 и выше к 2021 году.

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

Одно из наиболее перспективных в будущем разработок в области параллельных вычислений квантовые вычисления.

По мере приближения к концу закона Мура (который гласит, что число транзисторов в микросхемах удваивается каждые два года), исследователи пытаются найти способы сохранения экспоненциального роста скорости, с которой мы можем делать сложные вычисления. Квантовые компьютеры могут полностью революционизировать искусственный интеллект (которому уделяется время на курсах Machine Learning и Machine Learning и Deep Learning), конечно же, индустрию безопасности, которой посвящен наш отдельный курс по Этичному хакингу.

Узнайте, как прокачаться в других специальностях или освоить их с нуля:

Другие профессии и курсы
Подробнее..

Просветительская деятельность как профилактика синдрома самозванца

02.04.2021 10:12:46 | Автор: admin

Дисклеймер: я не психолог и даже не стремлюсь им стать. Если у вас уже имеются какие-то симптомы, лучше обратиться к специалистам. То что я буду описывать, это скорее метод профилактики и личный опыт.

Что такое синдром самозванца?

Тут было много статей на эту тему и я не буду повторять заново определения. Запишу свои соображения, откуда он берется и какие его принципы. Все мы знаем что какие-то знания или умения при их освоении кажутся сложными только пока ты их не освоил. После того как все нужные связи в мозгу образовались и оптимизировались, начинает казаться, ну чего тут сложного, раз раз и готово. Но это ощущение приходит только когда из области активного обдумывания, которая у нас не очень производительная, знания или умения уходят в более преспособленные для быстрого решения уже понятных задач зоны мозжечка и дефолт системы. Таким образом знания или умения покидают нашу сознательную часть и как бы становятся автоматическими, частью нас самих. Что в итоге происходит? Нам начинает казаться, что если нам не сложно выполнять ежедневную работу и она не вызывает никаких трудностей, то и сложной она не является и объективная оценка ценности, через субъективизацию, начинает падать, нам кажется, что мы занимаемся какой-то ерундой и она не заслуживает даже той оценки в виде нашей зарплаты и признания коллег, которая имеется.

Связь между выгорающем и синдромом самозванца

Более компетентные люди могут поправить меня в комментариях. Но я считаю, что эти два синдрома идут рука об руку и имеют общие корни. Когда тебе не кажется что ты делаешь что то значимое, что твои знания ценны, а действия меняют мир к лучшему. Тупое повторение ежедневных ритуалов и куча работы, которая по нашей собственной оценке не стоит того чтобы ее делать, предсказуемо ведет нас к полной потере интереса к той деятельности которую мы выполняем, заодно обесценивая и себя как профессионала . Мы не видим ничего нового, никакой мотивации к росту в профессии, потому что мозг привык к тому что делает автоматически и начинает попросту лениться. Зачем стремиться к чему-то, если все и так получается. Но без новых мотиваций, без новых применений нашим знаниям мы как раз и начинаем выгорать.

Как командная работа погубила нашу мотивацию

Все мы работаем в среде аджайл и подобных, эти ежедневные совещания, где все высказывают наболевшее, обсуждаются проблемы и их решения, каждого выслушают и все мирно обсудят. Но предствьте себе, как это необычно для нашего мозга, который эволюционно привык к взаимодействию в стае. Где есть вожак, высокоранговые обезьяны, низкоранговые. Где все понятно кого нужно слушать, а кого не нужно. Сейчас же мы все "решаем общую проблему" и в общем-то никто единый не диктует как мы ее будем решать, а между собой мы все равны, что хорошо с точки зрения процессов, но подтачивает мотивацию. Где бесконечно брать силы на новые рационализаторские предложения, если это просто скидывается в общий бэклог, разбивается на задачи и идет в работу, без какой либо ачивки в нашу систему вознаграждений в мозге. Да можно очень долго имитировать энтузиазм, но в такой схеме взаимодействий мы все видим к чему это приводит, падение мотивации, выгорание, синдром самозванца. Так что в итоге, просто смириться и ждать предсказуемого результата? Можно попробовать получить мотивацию на стороне. Ведь мозгу не важно откуда брать положительные подкрепления, у кого-то это могут быть хобби, какие-то личные проекты, любое занятие где у вас лично что-то хорошо получается и по результату ваш мозг выдает заветное "Какой ты молодец!".

Причем тут просветительская деятельность?

Раз уж мы пошли в объединения и обобщения всего и вся, давайте объясним просвятительскую деятельность. К ней я отношу любые выступления на конференциях, составления руководств и запись онлайн уроков, менторство. Любая деятельность где вы являетесь источником знаний и имеется какая-то другая сторона в виде одного или многих людей, которые принимают от вас эти знания. Не знаю, что сейчас будет с ней с приходом нового закона о контроле такой деятельности, но надеюсь нам не запретят выступать на конференциях и учить людей тому что мы знаем, иначе не видать нам профилактики выгорания и синдрома самозванца. Итак давайте рассмотрим что в нас есть и почему нам так важно этим делиться.

Как стать "вожаком" в своей стае

Есть один интересный эксперимент на приматах Конарда Лоренца. Где низкоранговую мартышку отселили от её стаи и научили доставать из специльной корбки банан. Потом подселили всех ее сородичей и дали им понаблюдать, как мартышка демонстрировала не доступное для всех остальных умение. Думаете все остальные тут же принялись за ней повторять? Как бы не так. Они просто били эту мартышку и отбирали банан, а её посылали за следующим. Потом эксперимент повторили с высокоранговым самцом. Его научили доставать банан и запустили остальных. Может потому что отобрать у него банан не представлялось возможным, может из за его авторитета. Но во втором случае все научились сами доставать бананы и история на этом закончилась. Выводы можно делать разные. Но в целом нам, в контексте статьи, будет важным предположение, что обучая кого-то, мы чувствуем себя чуть выше по рангу в этой стае и это подпитывает наш иерархиечский инстинкт. Ведь всем нам хочется быть оцененными, получить одобрение и какую-то похвалу. Так вот чем не метод самому себе организовать стаю и стать в ней "вожаком". Делясь знаниями, готовясь к конференциям, записывая какаие то руководства или уроки мы не только обеспечиваем себя аудиторией но и боремся с синдромами выгорания и самозванца. Потому что простая попытка изложить заново на бумагу или в печатном виде того, что для вас "просто" или само собой разумеется, заставляет вас самих крепко задуматься, так ли это просто, то чем вы занимаетесь. Я испытывал подобное проводя собеседования, когда кандидат, на вопросы, которые для вас кажутся элементарными, мнется и не знает что ответить, хотя, судя по его резюме обязательно должен был с этим столкнуться или хотя бы предположить, как можно решить подобную задачу, но на другом конце молчание и в вашей голове возникает мысль "хм, оказывается не все это знают". Готовясь к конференции или составляя план онлайн урока подключается еще и мысль как это объяснить условному новичку, что в этих знаниях является структурой, а что наполнением. Я даже не подозревал, какой положительный эффект на меня это окажет. Когда ты пытаешься структурировать то, что уже знаешь, приходит какой-то еще один, новый уровень понимания и удовольствие от того, что сейчас это еще и оценят по достоинству. (ну или захейтят в коментах, хотя с проф. знаниями вероятность поменьше)

"Правильная" командная работа

Я никогда не выступал на конференциях и не занимался чем-то подобным, мне всегда казалось, что люди делают это из тщеславия, мол посмотрите как я крут. Я не считал что мне необходима такая подпитка. Сев в пандемию дома, как все, я стал задумываться, чего же мне не хватает, почему мотивация стала падать? Но после того, как я почитал из различных источников, насколько для человека важно взаимодействие в команде, социализация и общая цель с группой людей, я стал искать выходы на такое взаимодействие. Казалось бы работа сама по себе должна давать нам это все, но как я писал выше, атмосфера равноправия и ритуалы аджайл это синтетическая командная работа, на самом деле мы не очень чувствуем ту цель и то взаимодейтсиве которое бы дало нашему мозгу ощущение "стаи" и принадлежности к ней.

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

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

Всем спасибо, надеюсь я донес свои не хитрые мысли объемно, на вопросы могу поотвечать в комментариях. Напишите ваши истории и методы, как вы справляетесь с надвигающимися симптомами наших профессиональных болячек.

Подробнее..

Перевод Дайте собачке погулять автоматическое открытие двери при помощи Raspberry Pi

06.04.2021 00:08:46 | Автор: admin

Работа дома хороший вариант для многих из нас. Можно больше времени проводить с семьей (хотя бы теоретически), включая питомцев. Мой офис находится на втором этаже, так что я не всегда замечаю, когда собака хочет погулять. Конечно, можно поставить звонок и научить ее звонить, чтобы понимать, когда выпускать животное наружу. Но зачем, если можно придумать over-engineered решение? Технологий никогда не бывает много.

В этом проекте используется машинное обучение, а именно обнаружение объектов. К счастью, даже если вы не слишком хорошо в нем разбираетесь, это ОЧЕНЬ простой проект для старта. Его основа уже обученная нейросеть, так что не придется тратить часы на то, чтобы получить сотни изображений, а потом обучать на их основе нейросеть.

Что нужно для старта


Raspberry Pi 4 или Raspberry Pi 3 с источником питания.
Карта памяти объемом в 8 ГБ или больше с Raspberry Pi OS.
Raspberry Pi камера и кабель для обнаружения объектов.
Модуль широкоугольного объектива для малинки. Ну или любой другой модуль камеры, который может вам понадобиться все зависит от того, на каком расстоянии от двери будет установлена эта камера.
Динамики с 3,5 мм штекером. Можно использовать и мегафон было бы желание.
Монитор и клавиатура (по желанию) с HDMI и набором кабелей.

Как определить, когда питомец хочет на улицу при помощи малинки


1. Настройте Raspberry Pi. Если не знаете как это сделать, вот туториал.
2. Подключите камеру к малинке.
3. Активируйте камеру при помощи raspi-config. Для этого необходимо зайти под администратором и перейти к Interface Options > P1 Camera.
4. Перезагрузка.



5. Тестируем фокус камеры при помощи команд, указанных ниже. Понятно, что картинка видна только если монитор подключен к ПК. Если используется headless версия rasbian, то нужно использовать scp для отправки изображения на компьютер.

raspistill -o /home/pi/focus.jpg

6. Ставим git. Для загрузки кода и скриптов из удаленного репозитория нужен git (мануал ну очень подробно разжеван, чтобы его могли использовать даже зеленые новички прим. Переводчика).

sudo apt-get update && sudo apt-get -y install git

7. Клонируем репозиторй с нужным кодом в собственную директорию.

cd ~/
git clone github.com/rydercalmdown/pet_detector


8. Устанавливаем зависимости, виртуальное окружение и python зависимости.

cd ~/pet_detector
make install


9. Загружаем заранее обученные модели. В проекте используется модель YOLOv3, обученная на дата-сете COCO. Модель умеет распознавать практически любые объекты в доме и квартире включая котов и собак.

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

say this is a test


11. Редактируем файл /etc/rc.local для запуска скрипта. Сначала нужно открыть файл при помощи команды sudo nano /etc/rc.local, а затем добавить вот эту строку.

source /home/pi/pet_detector/env/bin/activate && cd /home/pi/pet_detector/src && python app.py &

12. Направляем камеру на дверь. Конечно, если собака или кошка мечутся по квартире, такая настройка не очень помогает. Но если питомец садится и терпеливо ждет то все работает идеально.


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

Подробнее..

Перевод Оптимизация рабочего процесса при помощи fzf

05.04.2021 12:20:40 | Автор: admin

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


Обычные параметры моего рабочего процесса имена файлов и ветвей git: если посмотреть на мою историю команд, окажется, что git я ввожу чаще всего; ручной ввод команд git сопряжен с трудностями и часто приводит к ошибкам, поэтому я не ввожу команды руками везде, где это возможно. В зависимости от команды может подойти автозамена по табуляции, и она может оказаться очень полезной, но удобна она не всегда. В этом посте я покажу, как в качестве альтернативы использовать fzf.

Базовая функциональность fzf очень проста: он читает строки из стандартного потока ввода и даёт пользователю интерфейс, чтобы можно было выбрать одну или несколько строк и вписать их в стандартный поток вывода. Вики-страницы этого инструмента содержат массу примеров эффективного применения fzf. Это прекрасный ресурс, я взял несколько функций оттуда в свой репертуар и пользуюсь этими функциями почти каждый день, но в своей работе вы можете обнаружить очень специфические процессы, которых нет в вики, тогда как автоматизировать их было бы полезно.

Чтобы показать, как я подхожу к процессам подобного рода, я расскажу о 4 задачах, с которыми обычно сталкиваюсь. Затем напишу функцию оболочки с fzf, которая сделает работу удобнее. Кроме того, я расположу эти функции в порядке возрастания сложности:

В большинстве случаев я покажу простую функцию, которой достаточно почти для всех юзкейсов, а затем допишу её так, чтобы она стала удобнее или надёжнее.

Последние версии функций, включая варианты для fish, вы найдёте на Github.

Активация виртуальных сред python

Переменные моих виртуальных сред python содержится в файле ~/.venv. Вот, что я обычно делаю, чтобы активировать одну из сред:

  • начинаю ввод source ~/.venv/;

  • чтобы запустить автозавершение, нажимаю <tab>;

  • выбираю среду по желанию;

  • добавляю bin/activate и нажимаю <enter>.

Процесс можно улучшить чем-то вроде virtualenvwrapper, но есть и хороший пример с fzf: это простейшее решение, которое может занять всего одну строку.

function activate-venv() {  source "$HOME/.venv/$(ls ~/.venv/ | fzf)/bin/activate"}

activate-venv-simple.bash(download)

Активировать эту функцию можно с помощью команды:

source activate-venv-simple.bash

(добавьте этот код в свой .bashrc, чтобы он выполнялся постоянно), а затем используйте его, как показано ниже.

В окне выбора fzf показывает несколько виртуальных сред; среда активируется, когда строка выбрана.

Меньшая проблема то, что, если выйти из fzf нажатием ctrl-d, скрипт упадет с такой ошибкой:

bash: /home/crepels/.venv//bin/activate: No such file or directory

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

function activate-venv() {  local selected_env  selected_env=$(ls ~/.venv/ | fzf)  if [ -n "$selected_env" ]; then    source "$HOME/.venv/$selected_env/bin/activate"  fi}

Удаление веток git

Другим обнаруженным паттернам самоповторения оказалось удаление веток git. Как только фича смержена в основную ветку или эксперимент больше не нужен, ветка может быть удалена, но обычно я не удаляю её сразу: вместо этого ветки накапливаются, пока их количество не достигает критической точки, в которой навигация по веткам затрудняется. Когда дело в самом деле доходит до удаления веток, картина выглядит так:

  • я начинаю ввод git branch -D;

  • нажимаю табуляцию, чтобы вызвать автозавершение;

  • выбираю ветку, которую, как мне кажется, можно удалить.

Иногда я не уверен в том, какую ветку действительно можно удалить. Сначала мне нужно запустить команду git log в этой ветке, чтобы увидеть, что она содержит, и затем удалить её, как показано выше. Затем процесс повторяется до тех пор, пока я не удалю все залежавшиеся ветки.

Этот рабочий процесс хороший пример того, как сильно fzf упрощает работу. В этот раз мы воспользуемся опцией fzf --multi, которая позволяет по нажатию табуляции выбрать несколько записей.

function delete-branches() {  local branches_to_delete  branches_to_delete=$(git branch | fzf --multi)  if [ -n "$branches_to_delete" ]; then     git branch --delete --force $branches_to_delete  fi}

После выполнения source delete-branches-simple.bash мы можем использовать этот код следующим образом.

 Удаление веток при помощи fzf Удаление веток при помощи fzf

Код в основном работает, но реализовать эту функциональность можно по-разному. Первый вариант git branch показывает все ветки, включая ту, в которой мы находимся, она отмечена звёздочкой (*). Поскольку нельзя удалить ветку, в которой мы находимся, то и показывать её смысла нет, так что мы можем опустить эту ветку, предоставив вывод git branch команде grep --invert-match

Ещё один способ: мы можем пропустить переменным $branches_to_delete без кавычек в git branch -D. Сделать это нужно потому, что git каждая ветка нужна как отдельный аргумент. Если вы пользуетесь линтером вроде shallcheck, эта строка ему не понравится, поскольку переменные без кавычек могут вызвать глоббинг и разделение слов. В нашем случае срабатывание будет ложным: ветка не может содержать символов глоббинга; тем не менее я думаю, что избегать переменных без кавычек, где это возможно, хорошая практика, и один из способов сделать это пропустить вывод fzf через xargs прямо в git branch -D, а не хранить этот вывод в переменной. Если в xargs добавить опцию --no-run-if-empty, git будет вызываться только в том случае, если была выбрана хотя бы одна ветка.

Наконец, я упоминал, что, чтобы увидеть выбранную ветку, полезно посмотреть на вывод git log. Сделать это можно при помощи опции --preview: значением этой опции может быть какая-нибудь команда, которая будет выполняться всякий раз, когда в fzf будет выбрана новая строка, и вывод будет показан в окне предварительного просмотра. Фигурные скобки в этой команде работают как плейсхолдер, то есть заменяются на текущую выбранную строку.

function delete-branches() {  git branch |    grep --invert-match '\*' |    cut -c 3- |    fzf --multi --preview="git log {} --" |    xargs --no-run-if-empty git branch --delete --force}

Также обратите внимание на то, что вывод git branch пропускается через cut -с -3, которая из каждой строки удаляет 2 пробела. Если посмотреть на вывод git branch, видно, что каждая ветка, за исключением текущей, имеет префикс в 2 пробела. Если их не удалить, команда в --preview будет такой: git log ' branch-name', что приведёт к жалобам git на лишние начальные пробелы. В качестве альтернативы используйте команду git log {..}, которая тоже удалит пробелы из выбранной строки.

Вот пример: мы удаляем те же три ветки, что и выше, но при этом получаем больше информации.

Поток fzf для удаления ветвей в окне предварительного просмотра. Показаны ветки и вывод git log. Ударение ветвей с помощью fzf улучшенная версия.

Локально заходим в пул-реквест

Когда делается код-ревью, полезно бывает переключиться в ветку кода, который вы просматриваете . Интерфейс командной строки от гитхаба упрощает эту задачу: можно просто выполнить в репозитории команду пр pr-checkout. Так вы окажетесь в ветке соответствующего пул-реквеста и уже локально. Но как узнать номер пул-реквеста? Вот что я обычно делал:

  • открывал пул-реквест в браузере;

  • читал номер в URL;

  • переключался на окно терминала и вводил gh pr checkout, а затем номер.

Этот подход работает, когда мы имеем дело с пул-реквестом в 1 или 2 цифры, но, даже когда цифры всего 3, иногда я переключаюсь на браузер, чтобы убедиться, что запомнил номер правильно.

В моём прошлом посте я уже рассказывал, как при помощи gh автоматически опрашивал api Github, чтобы узнать номер пул-реквеста. Вы можете воспользоваться запросом к api, который я показываю ниже:

gh api 'repos/:owner/:repo/pulls'

Этот запрос возвращает массив JSON-объектов по одному объекту на каждый пул-реквест. Нам нужно конвертировать этот массив в подходящий fzf формат по строке на пул-реквест. Если говорить о данных, которые нам нужны, первое это номер пул-реквеста, который мы хотим пропустить через gh checkout. Также нам нужен способ идентифицировать интересный нам пул-реквест, в этом смысле лучший кандидат его заголовок. Чтобы извлечь эту информацию из JSON, мы можем воспользоваться интерполяцией строки в jq.

gh api 'repos/:owner/:repo/pulls' |    jq --raw-output '.[] | "#\(.number) - \(.title)"'

Вот опция сырого вывода --raw-output, которая определяет строку JSON; без неё каждая строка данных будет окружена кавычками. К примеру, если я выполню команду pr checkout https://github.com/junegunn/fzf, она выведет эти строки:

#2368 - ansi: speed up parsing by roughly 7.5x#2349 - Vim plugin fix for Cygwin 3.1.7 and above#2348 - [completion] Default behaviour to use fd if present else use find.#2302 - Leading double-quote for exact match + case sensitive search#2197 - Action accept-1 to accept a single match#2183 - Fix quality issues#2172 - Draft: Introduce --print-selected-count#2131 - #2130 allow sudo -E env fzf completion#2112 - Add arglist support to fzf.vim#2107 - Add instructions on command for installing fzf with Guix and/or Guix System#2077 - Use fzf-redraw-prompt in history widget#2004 - Milis Linux support#1964 - Use tmux shell-command#1900 - Prompt generally signals that the shell is ready#1867 - add {r}aw flag to disable quoting in templates#1802 - [zsh completion] Expand aliases recursively#1705 - Option to select line index of input feed and to output cursor line index#1667 - $(...) calls should be quoted: \"$(...)\"#1664 - Add information about installing using Vundle#1616 - Use the vim-specific shell instead of the environment variable#1581 - add pre / post completion 'hooks'#1439 - Suppress the zsh autocomplete line number output#1299 - zsh completion: Add support for per-command completion triggers.#1245 - Respect switchbuf option#1177 - [zsh] let key bindings be customized through zstyle#1154 - Improve kill completion.#1115 - _fzf_complete_ssh: support Include in ssh configs#559 - [vim] use a window-local variable to find the previous window#489 - Bash: Key bindings fixes

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

function pr-checkout() {  local pr_number  pr_number=$(    gh api 'repos/:owner/:repo/pulls' |    jq --raw-output '.[] | "#\(.number) \(.title)"' |    fzf |    sed 's/^#\([0-9]\+\).*/\1/'  )  if [ -n "$pr_number" ]; then    gh pr checkout "$pr_number"  fi}

Попробуем его на репозитории fzf.

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

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

В этой функции мы удаляем ветки выше и заполняем окно предварительного просмотра с помощью вызова git log в выбранной ветви. Первой идеей может быть попытка попробовать то, что я уже показывал, то есть сделать запрос к api, чтобы получить информацию о выбранном реквесте. Но если мы выбираем разные ветви, то задержка запроса к api может начать нас раздражать, затрудняя работу. К счастью, запросы api нам больше не понадобятся: все нужные данные у нас уже есть: мы получили их, когда сделали первый запрос. Что нам нужно это дописать шаблон строки jq, чтобы извлечь всю нужную информацию и затем воспользоваться функцией fzf, которая позволяет спрятать информацию входящих строк в окне выбора и показать её в окне предпросмотра.

fzf рассматривает каждую строку как массив полей. По умолчанию поля разделяются последовательностями пробелов (табуляциями и пробелами), но мы можем управлять разделителем с помощью опции --delimiter. Например, если мы зададим --delimiter=',' и передадим строку first,second,third в fzf, то поля будут first,, second и third. Само по себе это бесполезно. Но с помощью опции --with-nth мы можем управлять полями в окне выбора. Например, fzf --with-nth=1,2 будет отображать только первое и второе поля каждой строки. Кроме того, мы видели выше, что можно написать {} в качестве плейсхолдера в команде предварительного просмотра и fzf заменит его текущей выбранной строкой. Но {} это простейшая форма плейсхолдера. Можно указать индексы полей в фигурных скобках, и fzf заменит плейсхолдер этими полями.

Вот пример, где мы используем как --with-nth, так и --preview, а <tab> играет роль разделителя.

echo -e 'first line\tfirst preview\nsecond line\tsecond preview' |    fzf --delimiter='\t' --with-nth=1 --preview='echo {2}'

fzf разбивает каждую строку по символу табуляции; опция --with-nth=1 указывает fzf показать первую часть в окне выбора; {2} в команде предварительного просмотра будет заменена второй частью, и так как она передаётся в echo, то просто отобразится.

Пример работы с полями в fzfПример работы с полями в fzf

Этот скрипт мы используем, чтобы показать полезную информацию в окне предпросмотра. Давайте сначала просто посмотрим на него, а затем я расскажу, как он выполняется, шаг за шагом.

function pr-checkout() {  local jq_template pr_number  jq_template='"'\'#\(.number) - \(.title)'\'\t'\'Author: \(.user.login)\n'\'Created: \(.created_at)\n'\'Updated: \(.updated_at)\n\n'\'\(.body)'\'"'  pr_number=$(    gh api 'repos/:owner/:repo/pulls' |    jq ".[] | $jq_template" |    sed -e 's/"\(.*\)"/\1/' -e 's/\\t/\t/' |    fzf \      --with-nth=1 \      --delimiter='\t' \      --preview='echo -e {2}' \      --preview-window=top:wrap |    sed 's/^#\([0-9]\+\).*/\1/'  )  if [ -n "$pr_number" ]; then    gh pr checkout "$pr_number"  fi}

Мы немного изменили эту простую функцию. Извлекли шаблон строки jq в переменную, а затем дополнили её информацией об авторе, времени создания пул-реквеста, времени его последнего обновления, а также его описанием . Всю эту информацию мы получили в объекте JSON. Ответьте на этот запрос к api гитхаба: gh api 'repos/:owner/:repo/pulls'.

Обратите внимание, что мы отделили новую информацию номер и заголовок символом табуляции \t. Символ табуляции используется также в качестве разделителя в fzf, затем мы показываем номер пул-реквеста и заголовок в окне выбора (при помощи --with-nth=1), а оставшуюся информацию показываем в окне предварительного просмотра (при помощи --preview='echo -e {2}').

Обратите внимание также, что на этот раз в jq мы не используем опцию --raw-output. Причина немного неочевидна. Строки, которые мы создаём с помощью jq, содержат экранированные символы новой строки. Если мы передадим опцию --raw-output в jq, она будет интерпретировать все экранированные символы, и, в частности, вместо \n отобразится именно новая строка. Вот пример, сравните выходные данные этой команды:

echo '{}' | jq --raw-output '"first\nsecond"'

и команды

echo '{}' | jq '"first\nsecond"'

первая выведет

firstsecond

А вторая вот такую строку:

"first\nsecond"

Первая версия проблематична. Помните, что fzf работает со строками, делает список строк, позволяя пользователю выбрать одну или несколько строк и вывести их. Это означает, что без опции сырого вывода каждый пул-реквест в fzf будет показан как множество строк. И это определённо не то, чего мы хотим. Поэтому позволим jq вывести escape-версию, чтобы гарантировать, что каждый пул-реквест это одна строка.

Однако такой подход вводит новые проблемы, первая мы по-прежнему хотим настоящие символы новой строки, а не символы \n. Эта проблема решается командой echo -e, которая включает интерпретацию escape-символов. Вторая проблема в том, что без опции сырого вывода jq в начале и в конце строки показывает символы кавычек и распечатывает наш разделитель, то есть табуляцию, как символ в escape. Эту проблему мы решим удалением кавычек в ручном режиме и заменой первого escape-символа \t на настоящую табуляцию. Именно это делается в sed после jq.

Наконец, обратите внимание, что мы определили опцию --preview-window=top:wrap, чтобы fzf оборачивал строки в окне предпросмотра и отображал их верхней части экрана, а не справа.

И вот как это выглядит в действии:

Создание веток для фич из проблем (issues) в JIRA

Мы видели выше, как использовать fzf для удаления ветвей git. Теперь давайте посмотрим на противоположную задачу создание новых ветвей. На работе для отслеживания проблем мы используем JIRA. Каждая ветвь функции обычно соответствует какой-то проблеме JIRA. Чтобы поддерживать эту взаимосвязь, я использую схему именования ветвей git, о которой расскажу ниже. Предположим, что проект JIRA называется BLOG, и сейчас я работаю над проблемой BLOG-1232 с названием Добавить в сценарий запуска флаг вывода подробностей. Я называю свою ветку BLOG-1232/add-a-verbose-flag-to-the-startup-script; описание обычно даёт достаточно информации, чтобы определить функцию, которой соответствует ветвь, а часть BLOG-1232 позволяет мне перейти к тикету JIRA, когда я ищу подробности о проблеме.

Вполне понятно, как выглядит рабочий процесс создания этих веток:

  • вы открываете issue из JIRA в браузере;

  • копируете номер проблемы или запоминаете его;

  • переключаетесь на терминал, начинаете вводить git checkout -b BLOG-1232/;

  • переключаетесь на браузер и смотрите на название;

  • переключаетесь на терминал и добавляете похожее на название в JIRA описание в kebab-cased.

Обычно мне приходится несколько раз переключаться между браузером и терминалом, и я всё равно делаю опечатки в названии ветки.

И это ещё один рабочий процесс, который можно полностью автоматизировать. С проблемами в Jira можно работать так же, как мы работали с пул-реквестами, через API JIRA. Функция, которую мы напишем, подобна pr-checkout, но будет иметь несколько заметных отличий от неё.

Во-первых, от жира нет удобного инструмента, подобного gh, чтобы общаться с её api. Во-вторых, сервер (по крайней мере сервер, с которым работаю я) не разрешает создавать токены доступа, что заставляет меня при доступе к api использовать простые имя пользователя и пароль. Мне не хочется сохранить мой пароль в скрипте оболочки, а точнее, не хочется делать это в незашифрованном файле, поэтому, чтобы пароль хранился безопаснее, воспользуемся secret-tool. Наконец, создание имени ветки требует большего, чем простое извлечение текста; воспользуемся комбинаций cut, sed, и awk.

Давайте сначала посмотрим на скрипт, а потом попробуем понять, как он работает.

function create-branch() {  # The function expectes that username and password are stored using secret-tool.  # To store these, use  # secret-tool store --label="JIRA username" jira username  # secret-tool store --label="JIRA password" jira password  local jq_template query username password branch_name  jq_template='"'\'\(.key). \(.fields.summary)'\'\t'\'Reporter: \(.fields.reporter.displayName)\n'\'Created: \(.fields.created)\n'\'Updated: \(.fields.updated)\n\n'\'\(.fields.description)'\'"'  query='project=BLOG AND status="In Progress" AND assignee=currentUser()'  username=$(secret-tool lookup jira username)  password=$(secret-tool lookup jira password)  branch_name=$(    curl \      --data-urlencode "jql=$query" \      --get \      --user "$username:$password" \      --silent \      --compressed \      'https://jira.example.com/rest/api/2/search' |    jq ".issues[] | $jq_template" |    sed -e 's/"\(.*\)"/\1/' -e 's/\\t/\t/' |    fzf \      --with-nth=1 \      --delimiter='\t' \      --preview='echo -e {2}' \      --preview-window=top:wrap |    cut -f1 |    sed -e 's/\. /\t/' -e 's/[^a-zA-Z0-9\t]/-/g' |    awk '{printf "%s/%s", $1, tolower($2)}'  )  if [ -n "$branch_name" ]; then    git checkout -b "$branch_name"  fi}

В скрипте мы видим три части. Первая часть это команда curl, её переменные. Через них скрипт общается с API JIRA. Затем вывод api конвертируется строки формата, удобного для fzf; это часть скрипта такая же, как у pr-checkout. Наконец, вывод fzf конвертируется формат имени ветки.

Самые существенные изменения в сравнении с pr-checkout эта команда curl. Мы воспользовались конечной точкой поиска JIRA, которая в качестве параметра URL ожидает запрос на языке JQL. В моём случае меня интересуют все проблемы проекта BLOG, которые закреплены за мной, и те, что отмечены строкой In Progress. Строка запроса JQL содержит пробелы, знаки и скобки. Все они недопустимы в url, поэтому их нужно закодировать. Опция curl --data-urlencode автоматически закодирует эти символы. Поскольку в этой опции по умолчанию применяется запрос POST, чтобы переключиться на get, мы должны добавить опцию --get. Также воспользуемся опцией --user, чтобы сообщить curl, что нужно добавить заголовок базовой аутентификации. И последнее: добавим опцию --silent, чтобы опустить информацию о прогрессе выполнения и --compressed, чтобы сэкономить на пропускную способность.

Затем, чтобы конвертировать записи массива в JSON ответе в одну строку, воспользуемся той же техничкой, что и выше, разделив строку поиска в окне предпросмотра по символу табуляции и пропустив вывод через fzf, чтобы позволить пользователю выбрать запись. Вывод fzf будет строкой вроде BLOG-1232. Add a verbose flag to the startup script{...preview part}, чтобы удалить часть предварительного просмотра строки, воспользуемся командой cut. По умолчанию cut в качестве разделителя использует символ табуляции, а опция -f1 сообщает cut, что нужно вывести первое поле. Результат выполнения команды будет таким: BLOG-1232. Add-a-verbose-flag-to-the-startup-scrip. Затем команда sed заменит первую точку на символ табуляции, а все нечисловые и неалфавитные символы на -, сохранив при этом наши табуляции. И вот результат: BLOG-1232<tab>Add-a-verbose-flag-to-the-startup-script. Наконец, awk возьмёт строку, разделит её по табуляции, преобразует её вторую часть в нижний регистр и вернёт обе части символом косой черты в качестве разделителя.

 Создание новой ветки из проблем в JIRA Создание новой ветки из проблем в JIRA

Заключение

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

Представленные мной рабочие процессы могут никак не касаться вас. Но, надеюсь, вам поможет техника в целом: попробовать понаблюдать, как вы добавляете параметр к командам и как этот процесс можно автоматизировать. Параметры могут быть файлами или каким-то местом в системе, расположение которого не меняется, например, виртуальными средами. Или это могут быть параметры, которые пропускаются через другую команду (пример: ветви гита) или через API (номер пул-реквеста или заголовок из JIRA).

Узнайте, как прокачаться в других специальностях или освоить их с нуля:

Другие профессии и курсы
Подробнее..

Перевод Как сделать полнотекстовую поисковую машину на 150 строках кода Python

07.04.2021 20:14:16 | Автор: admin

Полнотекстовый поиск неотъемлемая часть нашей жизни. Разыскать нужные материалы в сервисе облачного хранения документов, найти фильм в Netflix, купить туалетную бумагу на Ozon или отыскать с помощью сервисов Google интересующую информацию в Интернете наверняка вы сегодня уже не раз отправляли похожие запросы на поиск нужной информации в невообразимых объёмах неструктурированных данных. И что удивительнее всего несмотря на то что вы осуществляли поиск среди миллионов (или даже миллиардов) записей, вы получали ответ за считанные миллисекунды. Специально к старту нового потока курса Fullstack-разработчик наPython в данной статье мы рассмотрим основные компоненты полнотекстовой поисковой машины и попытаемся создать систему, которая сможет за миллисекунды находить информацию в миллионах документов и ранжировать результаты по релевантности, причём всю систему можно воплотить всего в 150 строках кода на Python!


Данные

Весь код, использованный в данной статье, можно найти на Github. Здесь я приведу ссылки на фрагменты кода, и вы сами сможете попробовать с ним поработать. Весь пример можно запустить, установив файл requirements (pip install -r requirements.txt) и запустив на выполнение файл python run.py. Данная команда загрузит все данные и запустит пример поискового запроса с ранжированием и без ранжирования.

Перед тем как начать создание поисковой машины, нужно подготовить полнотекстовые неструктурированные данные, в которых будет осуществляться поиск. Искать будем в аннотациях статей из английской Википедии. Это заархивированный с помощью gzip утилиты сжатия и восстановления файлов XML-файл размером около 785 Мбайт, содержащий приблизительно 6,27 миллионов аннотаций [1]. Для загрузки архивированного XML-файла я написал простую функцию, но вы можете поступить проще загрузить его вручную.

Подготовка данных

Все аннотации хранятся в одном большом XML-файле. Аннотации в таком файле отделяются друг от друга элементом <doc> и выглядят примерно так (элементы, которые нас не интересуют, я опустил):

<doc>    <title>Wikipedia: London Beer Flood</title>    <url>https://en.wikipedia.org/wiki/London_Beer_Flood</url>    <abstract>The London Beer Flood was an accident at Meux & Co's Horse Shoe Brewery, London, on 17 October 1814. It took place when one of the  wooden vats of fermenting porter burst.</abstract>    ...</doc>

Интерес для нас представляют следующие разделы: title, url abstract (сам текст аннотации). Чтобы было удобнее обращаться к данным, представим документы как класс данных Python. Добавим свойство, конкатенирующее заголовок и содержание аннотации. Код можно взять здесь.

from dataclasses import dataclass@dataclassclass Abstract:    """Wikipedia abstract"""    ID: int    title: str    abstract: str    url: str    @property    def fulltext(self):        return ' '.join([self.title, self.abstract])

Затем нужно извлечь данные из XML-файла, осуществить их синтаксический разбор и создать экземпляры нашего объекта Abstract. Весь заархивированный XML-файл загружать в память не нужно, будем работать с потоком данных [2]. Каждому документу присвоим собственный идентификатор (ID) согласно порядку загрузки (то есть первому документу присваивается ID=1, второму ID=2 и т. д.). Код можно взять здесь.

import gzipfrom lxml import etreefrom search.documents import Abstractdef load_documents():    # open a filehandle to the gzipped Wikipedia dump    with gzip.open('data/enwiki.latest-abstract.xml.gz', 'rb') as f:        doc_id = 1        # iterparse will yield the entire `doc` element once it finds the        # closing `</doc>` tag        for _, element in etree.iterparse(f, events=('end',), tag='doc'):            title = element.findtext('./title')            url = element.findtext('./url')            abstract = element.findtext('./abstract')            yield Abstract(ID=doc_id, title=title, url=url, abstract=abstract)            doc_id += 1            # the `element.clear()` call will explicitly free up the memory            # used to store the element            element.clear()

Индексирование

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

Так выглядит книжный алфавитный указательТак выглядит книжный алфавитный указатель

Фактически мы создаём словарь, в котором будет проведено сопоставление всех слов нашего набора документов с идентификаторами документов, в которых встречаются эти слова. Выглядеть это будет примерно так:

{    ...    "london": [5245250, 2623812, 133455, 3672401, ...],    "beer": [1921376, 4411744, 684389, 2019685, ...],    "flood": [3772355, 2895814, 3461065, 5132238, ...],    ...}

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

Выделение лексемВыделение лексем

Анализ

Применим простейший способ выделения лексем: разобьём текст в местах, в которых встречаются пробелы. Затем к каждой лексеме применим пару фильтров: переведём текст лексемы в нижний регистр, удалим любые знаки препинания, исключим 25 наиболее распространённых английских слов (а также слово википедия, так как оно встречается во всех заголовках всех аннотаций) и к каждому слову применим фильтр выделения основы слова (после этой операции разные формы слова, например, красный и краснота будут соответствовать одной и той же основе красн [3]).

Функции выделения лексем и перевода в нижний регистр довольно просты:

import StemmerSTEMMER = Stemmer.Stemmer('english')def tokenize(text):    return text.split()def lowercase_filter(text):    return [token.lower() for token in tokens]def stem_filter(tokens):    return STEMMER.stemWords(tokens)

От знаков пунктуации избавиться также просто к набору пунктуационных знаков применяется регулярное выражение:

import reimport stringPUNCTUATION = re.compile('[%s]' % re.escape(string.punctuation))def punctuation_filter(tokens):    return [PUNCTUATION.sub('', token) for token in tokens]

Игнорируемые слова это самые распространённые слова, которые, как мы полагаем, будут встречаться практически в каждом документе. Включение в указатель игнорируемых слов нежелательно, так как по поисковому запросу будет выдаваться практически каждый документ, и результат поиска станет малоинформативен (не говоря уже о том, что он займёт значительный объём памяти). Поэтому во время индексирования мы такие слова отфильтруем. В заголовках аннотаций статей Википедии содержится слово Википедия, поэтому это слово мы также добавляем в список игнорируемых слов. В итоге мы внесли в список игнорируемых слов 25 самых распространённых слов английского языка, в том числе слово Википедия.

# top 25 most common words in English and "wikipedia":# https://en.wikipedia.org/wiki/Most_common_words_in_EnglishSTOPWORDS = set(['the', 'be', 'to', 'of', 'and', 'a', 'in', 'that', 'have',                 'I', 'it', 'for', 'not', 'on', 'with', 'he', 'as', 'you',                 'do', 'at', 'this', 'but', 'his', 'by', 'from', 'wikipedia'])def stopword_filter(tokens):    return [token for token in tokens if token not in STOPWORDS]

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

def analyze(text):    tokens = tokenize(text)    tokens = lowercase_filter(tokens)    tokens = punctuation_filter(tokens)    tokens = stopword_filter(tokens)    tokens = stem_filter(tokens)    return [token for token in tokens if token]

Индексирование набора документов

Создадим класс Index, в котором будет храниться указатель (index) и документы (documents). В словаре documents будут храниться классы данных по идентификатору (ID), а ключи указателя index будут представлять собой лексемы со значениями идентификаторов документов, в которых встречаются лексемы:

class Index:    def __init__(self):        self.index = {}        self.documents = {}    def index_document(self, document):        if document.ID not in self.documents:            self.documents[document.ID] = document        for token in analyze(document.fulltext):            if token not in self.index:                self.index[token] = set()            self.index[token].add(document.ID)

Поиск

Теперь, когда все лексемы проиндексированы, задача выполнения поискового запроса превращается в задачу анализа текста запроса с помощью того же анализатора, который мы применили к документам; таким образом, мы получим лексемы, которые будут совпадать с лексемами, имеющимися в указателе. Для каждой лексемы осуществим поиск в словаре, выявим идентификаторы документов, в которых встречается такая лексема. Затем выявим идентификаторы документов во всех таких наборах (другими словами, чтобы документ соответствовал запросу, он должен содержать все лексемы, присутствующие в запросе). После этого возьмём итоговой список идентификаторов документов и выполним выборку данных из нашего хранилища документов [4].

def _results(self, analyzed_query):    return [self.index.get(token, set()) for token in analyzed_query]def search(self, query):    """    Boolean search; this will return documents that contain all words from the    query, but not rank them (sets are fast, but unordered).    """    analyzed_query = analyze(query)    results = self._results(analyzed_query)    documents = [self.documents[doc_id] for doc_id in set.intersection(*results)]    return documentsIn [1]: index.search('London Beer Flood')search took 0.16307830810546875 millisecondsOut[1]:[Abstract(ID=1501027, title='Wikipedia: Horse Shoe Brewery', abstract='The Horse Shoe Brewery was an English brewery in the City of Westminster that was established in 1764 and became a major producer of porter, from 1809 as Henry Meux & Co. It was the site of the London Beer Flood in 1814, which killed eight people after a porter vat burst.', url='https://en.wikipedia.org/wiki/Horse_Shoe_Brewery'), Abstract(ID=1828015, title='Wikipedia: London Beer Flood', abstract="The London Beer Flood was an accident at Meux & Co's Horse Shoe Brewery, London, on 17 October 1814. It took place when one of the  wooden vats of fermenting porter burst.", url='https://en.wikipedia.org/wiki/London_Beer_Flood')]

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

def search(self, query, search_type='AND'):    """    Still boolean search; this will return documents that contain either all words    from the query or just one of them, depending on the search_type specified.    We are still not ranking the results (sets are fast, but unordered).    """    if search_type not in ('AND', 'OR'):        return []    analyzed_query = analyze(query)    results = self._results(analyzed_query)    if search_type == 'AND':        # all tokens must be in the document        documents = [self.documents[doc_id] for doc_id in set.intersection(*results)]    if search_type == 'OR':        # only one token has to be in the document        documents = [self.documents[doc_id] for doc_id in set.union(*results)]    return documentsIn [2]: index.search('London Beer Flood', search_type='OR')search took 0.02816295623779297 secondsOut[2]:[Abstract(ID=5505026, title='Wikipedia: Addie Pryor', abstract='| birth_place    = London, England', url='https://en.wikipedia.org/wiki/Addie_Pryor'), Abstract(ID=1572868, title='Wikipedia: Tim Steward', abstract='|birth_place         = London, United Kingdom', url='https://en.wikipedia.org/wiki/Tim_Steward'), Abstract(ID=5111814, title='Wikipedia: 1877 Birthday Honours', abstract='The 1877 Birthday Honours were appointments by Queen Victoria to various orders and honours to reward and highlight good works by citizens of the British Empire. The appointments were made to celebrate the official birthday of the Queen, and were published in The London Gazette on 30 May and 2 June 1877.', url='https://en.wikipedia.org/wiki/1877_Birthday_Honours'), ...In [3]: len(index.search('London Beer Flood', search_type='OR'))search took 0.029065370559692383 secondsOut[3]: 49627

Релевантность

С помощью элементарных команд Python мы создали довольно быстро работающую поисковую систему, но остался один аспект, которого явно не хватает в нашей маленькой поисковой машине, а именно не учтён принцип релевантности. Сейчас программа поиска составлена таким образом, что пользователь получает неупорядоченный список документов и должен сам выбирать из полученного списка действительно нужные ему документы. Но, если результатов очень много, справиться с такой задачей не под силу никакому пользователю (в нашем примере OR программа выдала почти 50000 результатов).

Вот тут-то и пригодится алгоритм ранжирования по релевантности, то есть алгоритм, который присваивал бы каждому документу собственный ранг насколько точно документ соответствует запросу, и затем упорядочивал бы полученный список по таким рангам. Самый примитивный и простой способ присвоения ранга документу при выполнении запроса состоит в том, чтобы просто подсчитать, как часто в таком документе упоминается конкретное слово. Идея вроде бы логичная: чем чаще в документе упоминается термин, тем больше вероятность того, что это именно тот документ, который мы ищем!

Частота вхождения терминов

Расширим наш класс данных Abstract, чтобы можно было вычислять и сохранять частоту вхождения терминов в процессе индексирования. Соответственно, если нам потребуется ранжировать наш неупорядоченный список документов, у нас будет для этого вся нужная информация:

# in documents.pyfrom collections import Counterfrom .analysis import analyze@dataclassclass Abstract:    # snip    def analyze(self):        # Counter will create a dictionary counting the unique values in an array:        # {'london': 12, 'beer': 3, ...}        self.term_frequencies = Counter(analyze(self.fulltext))    def term_frequency(self, term):        return self.term_frequencies.get(term, 0)

При индексировании должен осуществляется подсчёт частот вхождения терминов:

# in index.py we add `document.analyze()def index_document(self, document):    if document.ID not in self.documents:        self.documents[document.ID] = document        document.analyze()

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

def search(self, query, search_type='AND', rank=True):    # snip    if rank:        return self.rank(analyzed_query, documents)    return documentsdef rank(self, analyzed_query, documents):    results = []    if not documents:        return results    for document in documents:        score = sum([document.term_frequency(token) for token in analyzed_query])        results.append((document, score))    return sorted(results, key=lambda doc: doc[1], reverse=True)

Обратная частота документов

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

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

Обратная частота документов для термина определяется делением количества документов (N) в указателе на количество документов, содержащих термин, и взятием логарифма полученного частного.

Обратная частота документов (IDF); формула взята из https://moz.com/blog/inverse-document-frequency-and-the-importance-of-uniquenessОбратная частота документов (IDF); формула взята из https://moz.com/blog/inverse-document-frequency-and-the-importance-of-uniqueness

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

# index.pyimport mathdef document_frequency(self, token):    return len(self.index.get(token, set()))def inverse_document_frequency(self, token):    # Manning, Hinrich and Schtze use log10, so we do too, even though it    # doesn't really matter which log we use anyway    # https://nlp.stanford.edu/IR-book/html/htmledition/inverse-document-frequency-1.html    return math.log10(len(self.documents) / self.document_frequency(token))def rank(self, analyzed_query, documents):    results = []    if not documents:        return results    for document in documents:        score = 0.0        for token in analyzed_query:            tf = document.term_frequency(token)            idf = self.inverse_document_frequency(token)            score += tf * idf        results.append((document, score))    return sorted(results, key=lambda doc: doc[1], reverse=True)

Будущая работа

Мы создали элементарную информационно-поисковую систему всего из нескольких десятков строчек кода Python! Код целиком приведён на Github. Также я написал вспомогательную функцию, загружающую аннотации статей Википедии и создающую указатель. Установите файл requirements, запустите его в выбранной вами консоли Python и получайте удовольствие от работы со структурами данных и операциями поиска.

Данная статья написана с единственной целью привести пример реализации концепции поиска и продемонстрировать, что поисковые запросы (даже с ранжированием) могут выполняться очень быстро (например, на своём ноутбуке с медленным Python я могу осуществлять поиск и ранжирование среди 6,27 миллионов документов). Статью ни в коем случае не следует рассматривать как инструкцию по созданию программного обеспечения промышленного уровня. Моя поисковая машина запускается полностью в памяти ноутбука, но такие библиотеки, как Lucene, используют сверхпроизводительные структуры данных и даже оптимизируют дисковые операции, а такие программные комплексы, как Elasticsearch и Solr, распространяют библиотеку Lucene на сотни, а иногда и тысячи машин.

Но даже наш простенький алгоритм можно существенно улучшить. Например, мы молчаливо предполагали, что каждое поле документа вносит в релевантность одинаковый вклад, но, если поразмыслить, так быть не должно ведь термин, присутствующий в заголовке, очевидно, должен иметь больший вес, чем термин, встречающийся в содержании аннотации. Другой перспективной идеей может стать более продвинутый синтаксический анализ запроса должны ли совпадать все термины? только один термин? или несколько? Зная ответы на эти вопросы, можно повысить качество работы поисковых запросов. Также почему бы не исключить из запроса определённые термины? почему бы не применить операции AND и OR к отдельным терминам? Можно ли сохранить указатель на диск и вывести его, таким образом, за пределы оперативной памяти ноутбука?

Благодаря своей универсальности и распространённости, Python уже который год находится в топе языков программирования и де-факто стал основным языком для работы с данными. Если вы хотите расширить свои компетенции и освоить этот язык под руководством крутых менторов приходите на курс Fullstack-разработчик на Python.

Узнайте, как прокачаться в других инженерных специальностях или освоить их с нуля:

Другие профессии и курсы
  1. Аннотация это, как правило, первый абзац или первая пара предложений статьи в Википедии. Полный объём заархивированного XML-файла составляет приблизительно 796 Мбайт. Если вы захотите самостоятельно поэкспериментировать с кодом, можно воспользоваться доступными архивами меньшего размера (с ограниченным количеством аннотаций); синтаксический разбор и индексирование XML-файла займут довольно большое время и потребуют значительных объёмов памяти.

  2. Весь набор данных и указатель будут храниться в памяти, поэтому нет нужды также хранить в памяти необработанные данные.

  3. Много ли преимуществ даёт фильтр выделения основы слова? Это тема для отдельного обсуждения. Применение такого фильтра позволит уменьшить общий размер указателя (то есть уменьшить количество уникальных слов), однако операция выделения основы слова базируется на эвристике, и мы, сами того не желая, можем отсеять потенциально ценную информацию. Например, если слова университет, универсальный, университеты и универсиада усечь до основы универс, мы потеряем способность различать значения этих слов, а это отрицательно скажется на релевантности. Более подробная информация о выделении основы слов (и лемматизации) приведена в этой отличной статье.

  4. При решении задачи мы используем оперативную память ноутбука. Но на практике применяется другой способ, не связанный с хранением указателя в памяти. Поисковая система Elasticsearch хранит данные в обычном текстовом формате JSON на диске, в самой библиотеке Lucene (базовой библиотеке поиска и индексирования) хранятся только индексированные данные. Многие другие поисковые системы просто возвращают упорядоченный список идентификаторов документов, который затем используется для извлечения и выдачи пользователям данных из базы данных или другого сервиса. Особенно это актуально для крупных корпораций, в которых полное реиндексирование всех данных обходится недёшево. Как правило, в поисковой системе хранятся только данные, связанные с обеспечением релевантности (а не атрибуты, используемые только для презентационных целей).

  5. Для более глубокого понимания алгоритма рекомендую ознакомиться со следующими публикациями: What is TF-IDF? и Term frequency and weighting

Подробнее..

Раскладка Дворака личный опыт

08.04.2021 10:11:09 | Автор: admin

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

Под катом о том, как я переучивался и с какими трудностями эксплуатации столкнулся. Напоследок несколько выводов по итогам 7 лет эксплуатации.

Самые неудобные шорткаты для левой руки...Самые неудобные шорткаты для левой руки...

В свое время я узнал о раскладке Дворака из подкаста Радио-Т.

В двух словах о раскладке Дворака

Самая распространенная раскладка для английского языка QWERTY - наследие времен пишущих машинок. Она была создана для первой популярной серийной машинки Remington 1, фактически, став самым первым стандартом.

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

Дворак - не единственная альтернатива QWERTY для английского языка, но в ИТ-среде ее активно популяризуют, вероятно, благодаря существованию так называемого Дворака для программистов, адаптированного для набора кода.

Заинтересовавшись темой, я нашел видео у Sorax, где он в очень позитивном ключе отзывался об этой раскладке. Тогда я подумал: Я же программист! Моя работа и заключается в том, чтобы много печатать. И хотя скорость набора символов на английском языке у меня уже приближалась в среднем к 350 в минуту, решил поэкспериментировать. Тем более один из ведущих Радио-Т рассказывал, что пользуется Двораком наряду с QWERTY, переключаясь по необходимости, как мы переключаемся между английским и русским языками. Я предполагал действовать также - не терять QWERTY.

Как я заново учился печатать

Свои эксперименты я начал с Дворака для программистов под Ubuntu. Эта версия раскладки отличается важными мелочами - более удобным для кодинга расположением часто используемых скобок и цифр.

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

Для первой тренировки я использовал пакет dvorak7min. В нем 29 упражнений, которые учат правильно печатать и помогают запомнить, как буквы расположены по рядам. Благодаря этому консольному инструменту часа за четыре я освоил основные принципы. После этого все свои рабочие задачи выполнял уже в раскладке Дворака.

Я не менял кейкапы и не клеил наклейки на клавиатуру из принципиальных соображений. Всегда был адептом слепой печати и считал, что главное не смотреть на кнопки, а учиться в уме. Это действительно ускорило переход.

Два-три часа в день я тратил на тренажер, пока не заскучал с dvorak7min. А потом пошел на клавогонки (klavogonki.ru), чтобы следить за прогрессом. Выбрал специальный английский словарь и начал постепенно его проходить. Когда скорость подросла до 200 символов в минуту, я перешел на обычный английский словарь и еще месяц гонял на нем.

Честно скажу, первое впечатление было необычным. В раскладке Дворака гораздо больше работает правая рука. Я правша, но в первое время чувствовал, как именно правая устает на больших текстах. Спустя полтора месяца я подкачался и догнал свои 350 символов в минуту на английском языке, но уже в раскладке Дворака. Далее скорость удалось поднять еще немного - примерно до 400 символов в минуту.

Кстати, QWERTY в первое время я действительно хорошо помнил и использовал по необходимости. Но по мере появления привычки к Двораку, переключаться на QWERTY стало тяжелее.

Первые сложности и компромисс

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

Как раз в то время я пробовал себя в качестве преподавателя - по вечерам ездил в один институт читать лекции о разработке программного обеспечения. Учитывая статус совместителя, у меня не было постоянного рабочего места, куда я мог бы установить Дворак для программистов. Нас постоянно перемещали между аудиториями.

Раскладка Дворака присутствует во всех основных ОС, но Дворака для программистов там по умолчанию нет. Устанавливать его на рабочее место в очередной аудитории запрещали доменные политики безопасности. В итоге вся вторая работа у меня проходила в QWERTY, что мешало эффективному переходу. Так мне пришлось пойти на первый компромисс - ограничиться использованием обычного Дворака, который можно было включить везде. Моя жизнь стала чуть легче, и в целом плюсы Дворака не исчезли. Но это был компромисс!

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

Мои выводы по итогам 7 лет использования Дворака

С Двораком руки действительно устают меньше

Раскладка Дворака действительно хорошо продумана.

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

Дворак усложняет взаимодействие с коллегами в офисе

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

Я единственный раз физически поменял кейкапы на клавиатуре как раз из-за коллег. В команде мы периодически практиковали парное программирование, когда вы сидите за одним компьютером, обсуждаете задачу, делаете наброски. Но когда кто-то берет твою клавиатуру и пытается что-то сделать, приходится долго объяснять, почему все не так, а потом включать QWERTY, чтобы коллега мог как-то печатать. Измененные кейкапы были своего рода внешним символом того, что не сможешь просто взять и печатать на этой клавиатуре.

Проблема, кстати, симметрична. Сам ты тоже не можешь быстро перейти на другое рабочее место. Садясь за компьютер коллеги, ты начинаешь медленно вспоминать QWERTY, печатая буквально двумя пальцами. Одно дело, когда коллега в курсе твоих экспериментов с раскладками, но совсем другое, если он видит тебя первый раз. Представьте, в команду приходит новый человек, ты помогаешь ему с разворачиванием проектов, берешь его клавиатуру, но это не Дворак. Ты понимаешь, что включать на данном этапе альтернативную раскладку ему нет смысла. Но он-то видит, как ты - специалист с опытом, который должен его онбордить - медленно подбираешь нужные буквы и путаешься в шорткатах. Это выглядит как минимум странно.

Я не зря сделал акцент на офисе. Сейчас, когда я перешел на полную удаленку, проблема ушла. Взаимодействие с коллегами построено иначе, никто не садится за мое рабочее место и мне не надо бегать между компьютерами. А у себя я могу использовать то, что мне удобно.

Хотите Дворака? Забудьте о шорткатах

Я очень люблю шорткаты на клавиатуре. Но пользуясь альтернативной раскладкой, ты обрекаешь себя на вечные проблемы с ними. И это очередная серия компромиссов.

Привычные шорткаты, созданные под работу одной рукой, в Двораке нажимаются иначе. Вот привык ты нажимать Ctrl+B в своем рабочем инструменте, но на тот же шорткат в Двораке срабатывает другая команда.

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

Хорошо, если нужная буква окажется под той же рукой. Но вообще говоря, это не гарантировано. Например, все привыкли, что в vim буквы hjkl используются как стрелки. Но в Двораке они расположены там, где в QWERTY-раскладке находятся буквы cv и jp. В итоге перемещение по тексту в редакторе осуществляется двумя руками. Левая рука отвечает за движение вниз-вверх, правая - влево-вправо.

На картинке выше (повторю ее тут для удобства) я отметил буквы, шорткаты с которыми перестают быть удобным для левой руки. Зеленые - неудобно, красные - совсем беда. Тут приходится либо использовать две руки, либо учиться нажимать правый Ctrl (Command).

Шорткаты для левой руки в ДворакеШорткаты для левой руки в Двораке

Конечно, шорткаты можно перенастроить с помощью конфигурации используемых инструментов или ремапперов, вроде Karabiner Elements (для MAC). И я это делаю, но все не так просто.

Готовых схем шорткатов под используемые мной программы я не видел. Самостоятельно переназначать надо так, чтобы не испортить другие команды, т.е. парой самых необходимых действий не ограничишься. Это требует времени, а значит перенастраивать имеет смысл в тех инструментах, которые ты используешь продолжительное время и не собираешься менять. Их на самом деле не так много. В остальном софте придется пользоваться мышью или стандартными не-Дворак шорткатами.

Даже если ты все под себя настроил (или выучил стандартные шорткаты в новой раскладке), проблемы останутся.

Тебе надо постоянно следить за тем, какая включена раскладка - русская или английский Дворак. Потому что в русском языке шорткаты работают, как в QWERTY. Я пытался ремапить шорткаты так, чтобы они работали одинаково на русском и английском языках, но у меня ничего не вышло.

Да, есть некоторые универсальные сочетания, но они работают не на всех ОС. Например, если бы я пользовался Windows или Ubuntu, я мог бы копировать и вставлять информацию через Ctrl / Shift + Ins, которые работали бы вне зависимости от включенной раскладки. Но в MAC этот универсальный способ не работает.

Лично я 90% времени нахожусь в английской раскладке, поэтому приучил себя пользоваться некоторыми функциями - в частности, упомянутыми копированием и вставкой информации - только в Двораке. Правда, из-за этого я теперь не могу пользоваться теми же шорткатами на чужом рабочем месте (Ctrl+C и Ctrl+V в QWERTY в других местах).

Еще один слой проблем - поголовное отсутствие тестирования на не-QWERTY раскладках. Подсказки ввода, заботливый автоперевод языка, который есть в некоторых веб-формах, не будут корректно работать, потому что никто не адаптирует эти инструменты под Дворака.

Я недавно купил себе MAC на новом чипе. Установил WebStorm, который JetBrains под него адаптировал. Но когда я нахожусь в раскладке Дворака, шорткаты у меня срабатывают дважды. Выполняется и команда, зарезервированная за буквой в QWERTY-раскладке, и команда на Двораке. Придется ждать фикса.

Видимо, какие-то такие проблемы будут преследовать поклонника Дворака всегда. Ты будешь бета-тестером новых инструментов для альтернативных раскладок.

На мой взгляд оно того не стоит

Для меня итогом этого многолетнего эксперимента фактически стала лишняя сотня символов в минуту на английском языке.

Раскладка Дворака определенно имеет смысл для больших текстов на английском. Но уже после перехода я понял, что как программист не пишу большие тексты. 90% рабочего времени я читаю код (зачастую, чужой) и думаю над тем, как лучше писать, нежели как быстрее это делать. Кодогенерация фреймворков и сниппеты редакторов кода давно и хорошо решают проблемы с шаблонными кусками. Поэтому скорость набора для меня не так уж и важна. Если бы сейчас меня кто-то спросил, стоит ли переходить, я бы не рекомендовал. В большей степени я тогда хотел чего-то нового и необычного. И я это получил в полной мере.

У меня сложилось впечатление, что если бы я просто гонял на клавагонках на QWERTY-раскладке, получил бы те же 400 символов в минуту, затратив меньше усилий. Так что второй раз я бы не стал уже начинать этот эксперимент. Слишком много неожиданных подводных камней.

Вместо вывода

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

Следующим экспериментом по совершенствованию работы для меня стал vim. Вместе с пониманием, что скорость печати не так принципиальна, я осознал, что гораздо важнее, насколько безошибочно ты пишешь и в целом насколько эффективно ты используешь свои основные инструменты (ту же IDEA). Vim позволяет работать с кодом более продуктивно и выполнять объемные операции с текстом через макросы. В этом смысле он дает гораздо больший прирост производительности.

У меня иногда закрадывается мысль отказаться от Дворака. Но я привык использовать некий симбиоз Дворака и vim. Если затею обратный переход, придется переучиваться.

Автор: Сергей Широковских, Максилект.

P.S. Мы публикуем наши статьи на нескольких площадках Рунета. Подписывайтесь на наши страницы в VK, FB, Instagram или Telegram-канал, чтобы узнавать обо всех наших публикациях и других новостях компании Maxilect.

Подробнее..

Перевод Как считывать и удалять метаданные из ваших фотографий с помощью Python

12.04.2021 16:18:43 | Автор: admin

Те, кто знает Python, могут делать поистине удивительные вещи, например, создавать арт-объекты и игры и красивые карты, полнотекстовую поисковую машину и систему распознавания лиц. Применим Python и для вполне бытовых задач. Сегодня, специально к старту новых потоков курсов Python для веб-разработки и Fullstack-разработчик на Python поделимся с вами туториалом, как считывать, добавлять и удалять EXIF метаданные из фотографий с помощью Python.


Немного очевидного для тех кто не в теме метаданные в фото

Массовое распространение смартфонов (по сути, портативных, оснащённых датчиками, всегда подключённых к сети компьютеров) привело к двум важным последствиям влиянию на конфиденциальность и влиянию на безопасность, и это ещё не до конца изучено:

  1. У большого количества людей есть камера, которая обычно находится в пределах досягаемости.

  2. По умолчанию фотографии, сделанные на камеру, могут выдавать конфиденциальную информацию, и многие пользователи не подозревают об этом.

Помимо данных изображения фотографии, сделанные с помощью смартфонов и современных цифровых камер, содержат метаданные, которые являются дополнительной информацией о фотографии. Эти метаданные хранятся в формате EXIF (сокращение от EXchangeable Image File format), который является постоянно развивающимся стандартом для информации, добавляемой к цифровым изображениям и звукозаписям.

На фотографиях EXIF может включать такую информацию, как:

  • Размеры и плотность пикселей фото.

  • Марка и модель устройства, на котором был сделан снимок.

  • Масштабирование, диафрагма, вспышка и другие настройки камеры при съёмке фотографии.

  • Ориентация устройства при фотографировании.

  • Когда было сделано фото.

  • Где было сделано фото.

  • В каком направлении была обращена камера.

  • Высота, на которой был сделан снимок.

Эти метаданные полезны для сортировки, каталогизации и поиска фотографий, поэтому был определён стандарт EXIF. Однако при этом возникают проблемы с конфиденциальностью и безопасностью, которые многие пользователи не принимают во внимание.

Одним из первых предостережений об EXIF является инцидент с конфиденциальностью в 2012 году, связанный с основателем антивирусной компании Джоном Макафи. Это было захватывающее время в жизни Макафи, поскольку он уклонялся от действий правоохранительных органов, но при этом давал журналистам эксклюзивные, пользующиеся большим спросом интервью. Один журналист, которому посчастливилось взять интервью, решил похвастаться своей удачей, опубликовав фотографию Макафи, но предварительно не удалив EXIF-данные. Они и раскрыли местонахождение Макафи и привели к его аресту.

Вы, вероятно, знаете о недавних историях, когда правоохранительные органы арестовывали подозреваемых, используя фотографии, размещённые в социальных сетях, потому что подозреваемые не принимали меры предосторожности и не очищали свои данные EXIF в процессе загрузки.

Я подозреваю, что вы как разработчики, заботящиеся о безопасности, вероятно, задаёте себе следующие вопросы:

  • Как я могу программно обнаружить и прочитать EXIF-метаданные с фотографии?

  • Как я могу программно изменять, добавлять или удалять EXIF-метаданные?

Если на вашем компьютере установлен Python 3.6 или более поздней версии, вы можете узнать это, выполнив приведённые ниже инструкции. Они охватывают пару пакетов Python, которые вы можете включить в свои приложения для извлечения, добавления, изменения или удаления EXIF-данных с фотографий. Попутно вы не только будете использовать свои навыки программирования, но и поработаете детективом!

Модуль exif

Существует ряд модулей Python, которые могут получить доступ к данным EXIF в цифровых фотографиях. В этой статье мы сосредоточимся на exif. Его API настолько питонический, что кажется, будто он является частью языка, а не модулем.

Чтобы установить exif, используйте pip, введя в командной строке следующее:

pip install exif

Если при вводе этой команды выдаётся сообщение об ошибке, попробуйте вместо этого использовать команду pip3 install exif. pip3 это версия pip, менеджера пакетов Python, специально предназначенная для Python 3.

Если вы не поддерживаете какой-либо код на Python 2, но вам нужно использовать pip3 для установки пакетов Python, то вам следует подумать об обновлении Python.

Загрузка фотографий и проверка их на наличие данных EXIF

Давайте проверим exif в работе. Рассмотрим эти две фотографии, palmtree1.jpg и palmtree2.jpg:

Предположим, вам задали следующие вопросы:

  1. Были ли эти фотографии сделаны на одно устройство или на разные?

  2. Какое фото было сделано первым?

  3. Где были сделаны эти фотографии?

Чтобы ответить на эти вопросы, мы загрузим данные из этих фотографий в объекты exif-Image, а затем будем использовать эти объекты для проверки EXIF-метаданных:

from exif import Imagewith open("./images/palm tree 1.jpg", "rb") as palm_1_file:    palm_1_image = Image(palm_1_file)    with open("./images/palm tree 2.jpg", "rb") as palm_2_file:    palm_2_image = Image(palm_2_file)    images = [palm_1_image, palm_2_image]

Код открывает каждый файл только для чтения. Он считывает данные файла в двоичном формате в объект файла, который затем используется для создания экземпляра объекта exif-Image. Наконец, он помещает объекты Image в массив, чтобы мы могли перебирать их, выполняя одни и те же операции с EXIF-метаданными каждой фотографии.

Давайте выполним нашу первую операцию: убедимся, что фото действительно содержат EXIF-данные. Мы сделаем это, проверив свойство has_exif каждого объекта Image. Для каждого изображения, содержащего EXIF-данные, мы будем использовать свойство изображения exif_version, чтобы отобразить версию EXIF:

for index, image in enumerate(images):    if image.has_exif:        status = f"contains EXIF (version {image.exif_version}) information."    else:        status = "does not contain any EXIF information."    print(f"Image {index} {status}")

При запуске этот код даёт следующие результаты:

Image 0 contains EXIF (version 0220) information.Image 1 contains EXIF (version 0232) information.

Теперь мы знаем, что обе фотографии содержат информацию EXIF и используют разные версии EXIF. Скорее всего, эти фотографии были сделаны на разные камеры.

Какие метаданные EXIF доступны на каждой фотографии?

Думайте о EXIF как о структуре данных ключ-значение, подобной словарю Python. Пары ключ-значение EXIF называются тегами, и каждый тег может содержать строковое или числовое значение. В текущем стандарте EXIF (версия 2.32) есть десятки тегов, и каждый от производителей смартфонов и камер до фотографов может добавлять свои собственные теги.

Вот полный список тегов EXIF, которые вы, вероятно, найдёте на цифровых фотографиях. Кроме того, тут есть теги, не входящие в стандарт EXIF, но предоставляемые рядом устройств или программного обеспечения.

EXIF один из тех неформальных форматов, где производители сами выбирают, какие функции они будут реализовывать. Это означает, что фотографии, снятые разными камерами и смартфонами, будут иметь разные наборы тегов EXIF.

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

Учитывая различия между устройствами и наличие инструментов для редактирования данных EXIF, первое, что вы должны сделать при работе с EXIF данными фотографии, это посмотреть, какие теги доступны.

Объекты Image, предоставляемые модулем exif, представляют теги EXIF как свойства этого объекта. Это означает, что вы можете использовать встроенную функцию Python dir() для объекта Image, чтобы увидеть, какие теги EXIF у него есть.

Следующий код отображает список тегов каждого объекта Image в нашем списке изображений:

image_members = []for image in images:    image_members.append(dir(image))for index, image_member_list in enumerate(image_members):    print(f"Image {index} contains {len(image_member_list)} members:")    print(f"{image_member_list}\n")

Вы увидите следующий результат:

Image 0 contains 53 members:['_exif_ifd_pointer', '_gps_ifd_pointer', '_segments', 'aperture_value', 'brightness_value', 'color_space', 'components_configuration', 'datetime', 'datetime_digitized', 'datetime_original', 'delete', 'delete_all', 'digital_zoom_ratio', 'exif_version', 'exposure_bias_value', 'exposure_mode', 'exposure_program', 'exposure_time', 'f_number', 'flash', 'flashpix_version', 'focal_length', 'focal_length_in_35mm_film', 'get', 'get_file', 'get_thumbnail', 'gps_altitude', 'gps_altitude_ref', 'gps_datestamp', 'gps_latitude', 'gps_latitude_ref', 'gps_longitude', 'gps_longitude_ref', 'has_exif', 'light_source', 'make', 'max_aperture_value', 'metering_mode', 'model', 'orientation', 'photographic_sensitivity', 'pixel_x_dimension', 'pixel_y_dimension', 'resolution_unit', 'scene_capture_type', 'sensing_method', 'shutter_speed_value', 'subsec_time', 'subsec_time_digitized', 'subsec_time_original', 'white_balance', 'x_resolution', 'y_resolution']Image 1 contains 68 members:['<unknown EXIF tag 316>', '<unknown EXIF tag 322>', '<unknown EXIF tag 323>', '<unknown EXIF tag 42080>', '_exif_ifd_pointer', '_gps_ifd_pointer', '_segments', 'aperture_value', 'brightness_value', 'components_configuration', 'datetime', 'datetime_digitized', 'datetime_original', 'delete', 'delete_all', 'exif_version', 'exposure_bias_value', 'exposure_mode', 'exposure_program', 'exposure_time', 'f_number', 'flash', 'flashpix_version', 'focal_length', 'focal_length_in_35mm_film', 'get', 'get_file', 'get_thumbnail', 'gps_altitude', 'gps_altitude_ref', 'gps_dest_bearing', 'gps_dest_bearing_ref', 'gps_horizontal_positioning_error', 'gps_img_direction', 'gps_img_direction_ref', 'gps_latitude', 'gps_latitude_ref', 'gps_longitude', 'gps_longitude_ref', 'gps_speed', 'gps_speed_ref', 'has_exif', 'lens_make', 'lens_model', 'lens_specification', 'make', 'maker_note', 'metering_mode', 'model', 'offset_time', 'offset_time_digitized', 'offset_time_original', 'orientation', 'photographic_sensitivity', 'pixel_x_dimension', 'pixel_y_dimension', 'resolution_unit', 'scene_capture_type', 'scene_type', 'sensing_method', 'shutter_speed_value', 'software', 'subject_area', 'subsec_time_digitized', 'subsec_time_original', 'white_balance', 'x_resolution', 'y_resolution']

Как вы можете видеть, в то время как оба объекта Image имеют много общих тегов, изображение 1 содержит немного больше, чем изображение 0. Это означает, что изображение 1 имеет несколько больше тегов EXIF, чем изображение 0. Это сильный индикатор того, что изображение 0 и изображение изображение 1 было снято на разные устройства.

Вы можете использовать стандартный метод set() для определения общих элементов изображения 0 и изображения 1:

common_members = set(image_members[0]).intersection(set(image_members[1]))common_members_sorted = sorted(list(common_members))print("Image 0 and Image 1 have these members in common:")print(f"{common_members_sorted}")

Запуск этого кода даёт следующий результат:

Image 0 and Image 1 have these members in common:['_exif_ifd_pointer', '_gps_ifd_pointer', '_segments', 'aperture_value', 'brightness_value', 'components_configuration', 'datetime', 'datetime_digitized', 'datetime_original', 'delete', 'delete_all', 'exif_version', 'exposure_bias_value', 'exposure_mode', 'exposure_program', 'exposure_time', 'f_number', 'flash', 'flashpix_version', 'focal_length', 'focal_length_in_35mm_film', 'get', 'get_file', 'get_thumbnail', 'gps_altitude', 'gps_altitude_ref', 'gps_latitude', 'gps_latitude_ref', 'gps_longitude', 'gps_longitude_ref', 'has_exif', 'make', 'metering_mode', 'model', 'orientation', 'photographic_sensitivity', 'pixel_x_dimension', 'pixel_y_dimension', 'resolution_unit', 'scene_capture_type', 'sensing_method', 'shutter_speed_value', 'subsec_time_digitized', 'subsec_time_original', 'white_balance', 'x_resolution', 'y_resolution']

Если вы смотрели EXIF-теги в документации (либо список стандартных тегов EXIF, либо расширенный список), вы могли заметить, что имена тегов EXIF находятся в PascalCase, а свойства EXIF в объектах exif-Image в snake_case. Это связано с тем, что авторы модуля exif стремятся следовать руководству по стилю Python и разработали Image для преобразования имён тегов EXIF в имена свойств Python.

Члены класса Image exif, не являющиеся тегами EXIF

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


Члены класса

Описание

delete(attribute)

Удаляет из изображения тег EXIF, указанный в строковом атрибуте.

delete_all

Удаляет все теги EXIF из изображения.

get(attribute, default=None)

Возвращает значение тега EXIF, заданное строковым атрибутом. Если тег недоступен или содержит значение, он возвращает значение, указанное в аргументе ключевого слова по умолчанию.

get_file

Возвращает текущие данные изображения, отформатированные для записи в двоичный файл.

get_thumbnail

Возвращает двоичные данные для эскиза изображения.

has_exif

Логическое значение, которое возвращает True, если изображение в настоящее время содержит метаданные EXIF.

set(attribute, value)

Установить значение для тега EXIF, заданное строковым атрибутом. Если тег недоступен или содержит значение, он возвращает значение, указанное в аргументе ключевого слова по умолчанию.

В этой статье мы рассмотрим большинство из этих свойств и методов.

Получение основной информации о фотографиях

Ответим на первый вопрос об этих фотографиях. Были ли они сняты на одно устройство или на разные? У нас уже есть основания полагать, что ответ нет.

Марка и модель устройства, на котором было сделано фото.

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

for index, image in enumerate(images):    print(f"Device information - Image {index}")    print("----------------------------")    print(f"Make: {image.make}")    print(f"Model: {image.model}\n")

Вот результат кода выше:

Device information - Image 0----------------------------Make: motorolaModel: motorola one hyperDevice information - Image 1----------------------------Make: AppleModel: iPhone 12 Pro

Это подтверждает, что фотографии были сделаны на разных устройствах, и теперь мы знаем детали.

Дополнительная информация об устройствах

Давайте соберём дополнительную информацию об устройствах, которые используются для фотосъёмки, а именно об их объективах и версиях операционной системы.

Не все устройства сообщают тип линзы в своих EXIF-метаданных, поэтому мы будем использовать метод Image get(), который аналогичен методу get(), используемому в Python. Подобно методу get() в Python, метод get(), предоставляемый объектом exif Image, изящно обрабатывает случай, когда данный ключ не существует.

В приведённом ниже коде используется get(), чтобы попытаться получить доступ к версиям объектива и операционной системы, используемым при съёмке фотографий. Если определённого свойства не существует, его значение будет отображаться как Неизвестно:

for index, image in enumerate(images):    print(f"Lens and OS - Image {index}")    print("---------------------")    print(f"Lens make: {image.get('lens_make', 'Unknown')}")    print(f"Lens model: {image.get('lens_model', 'Unknown')}")    print(f"Lens specification: {image.get('lens_specification', 'Unknown')}")    print(f"OS version: {image.get('software', 'Unknown')}\n")

Вот его результат:

Lens and OS - Image 0---------------------Lens make: UnknownLens model: UnknownLens specification: UnknownOS version: UnknownLens and OS - Image 1---------------------Lens make: AppleLens model: iPhone 12 Pro back triple camera 4.2mm f/1.6Lens specification: (1.5399999618512084, 6.0, 1.6, 2.4)OS version: 14.3

Обратите внимание, что телефон, используемый для съёмки изображения 0 (Motorola One Hyper), не предоставляет свойства lens_make, lens_model, lens_specification или software. Если бы мы попытались получить к ним доступ напрямую (например, image.lens_make), результатом была бы ошибка. Метод get() позволил нам предоставить альтернативное значение для этих несуществующих свойств.

Дата и время, когда была сделана фотография

Следующий вопрос: какое фото было сделано первым?

Мы можем узнать это, просмотрев свойство datetime_original каждой фотографии, которое указывает на дату и время, когда фотография была сделана. Процессор смартфона достаточно быстр, чтобы записывать точную долю секунды, когда он делает фотографию, и это значение сохраняется в свойстве subsc_time_original.

Некоторые телефоны также записывают свойство offset_time, которое мы можем использовать для определения смещения datetime относительно UTC.

Следующий код отображает дату и время, когда была сделана каждая из фотографий. Если фотография включает данные о временном сдвиге, код также отобразит это значение:

for index, image in enumerate(images):    print(f"Date/time taken - Image {index}")    print("-------------------------")    print(f"{image.datetime_original}.{image.subsec_time_original} {image.get('offset_time', '')}\n")

Вот результаты:

Date/time taken - Image 0-------------------------2021:01:22 15:08:46.327211 Date/time taken - Image 1-------------------------2021:01:22 15:08:59.383 -05:00

Как видно из вывода, изображение 0 было снято первым, а изображение 1 было снято через 13 секунд.

Определение места, где была сделана фотография

В этом разделе мы рассмотрим доступ к GPS-координатам в метаданных фотографии, форматирование этих координат и упрощение понимания этих координат путём их размещения на карте и преобразования их в названия страны, региона и города, где фото было сделано.

Получение GPS-координат фотографии

Формат EXIF определяет ряд тегов, начинающихся с gps, которые содержат полезную информацию о геолокации, включая широту и долготу, где была сделана фотография:

for index, image in enumerate(images):    print(f"Coordinates - Image {index}")    print("---------------------")    print(f"Latitude: {image.gps_latitude} {image.gps_latitude_ref}")    print(f"Longitude: {image.gps_longitude} {image.gps_longitude_ref}\n")

Вот результат кода выше:

Coordinates - Image 0---------------------Latitude: (28.0, 0.0, 1.56) NLongitude: (82.0, 26.0, 59.04) WCoordinates - Image 1---------------------Latitude: (28.0, 0.0, 1.54) NLongitude: (82.0, 26.0, 58.75) W

Обратите внимание, что свойства gps_latitude и gps_longitude возвращают широту и долготу в виде кортежа из трёх значений:

  1. Градусы.

  2. Минуты (1/60 градуса).

  3. Секунды (1/60 минуты или 1/3600 градуса).

Широта определяет угловое расстояние от экватора, которое может быть северным или южным. Свойство gps_latitude_ref указывает это направление, которое может быть N или S.

Долгота определяет угловое расстояние от меридиана, которое может быть восточным или западным. Свойство gps_longitude_ref указывает это направление: E или W.

Возможно, вы заметили небольшую разницу между координатами, указанными на фотографиях. Это ожидаемо: даже одно и то же устройство, расположенное в одном месте, в разное время будет сообщать немного разные координаты. Расхождение в координатах, сообщаемых телефонами, составляет порядка долей секунды, что соответствует примерно 25 футам или 7,6 метрам.

Форматирование широты и долготы

Давайте определим пару функций для форматирования информации о широте и долготе, возвращаемой Image, в стандартные форматы:

  • Градусы, минуты и секунды. В этом формате широта изображения 0 будет записана как 28.0 0.0 '1.56 "N.

  • Десятичные градусы. В этом формате широта изображения 0 будет записана как 28,000433333333334. Северные широты и восточные долготы представлены положительными значениями, в то время как южные широты и западные долготы представлены отрицательными значениями.

Вот определения этих функций, а также некоторый код, который их использует:

def format_dms_coordinates(coordinates):    return f"{coordinates[0]} {coordinates[1]}\' {coordinates[2]}\""def dms_coordinates_to_dd_coordinates(coordinates, coordinates_ref):    decimal_degrees = coordinates[0] + \                      coordinates[1] / 60 + \                      coordinates[2] / 3600        if coordinates_ref == "S" or coordinates_ref == "W":        decimal_degrees = -decimal_degrees        return decimal_degreesfor index, image in enumerate(images):    print(f"Coordinates - Image {index}")    print("---------------------")    print(f"Latitude (DMS): {format_dms_coordinates(image.gps_latitude)} {image.gps_latitude_ref}")    print(f"Longitude (DMS): {format_dms_coordinates(image.gps_longitude)} {image.gps_longitude_ref}\n")    print(f"Latitude (DD): {dms_coordinates_to_dd_coordinates(image.gps_latitude, image.gps_latitude_ref)}")    print(f"Longitude (DD): {dms_coordinates_to_dd_coordinates(image.gps_longitude, image.gps_longitude_ref)}\n")

Вот результат:

Coordinates - Image 0---------------------Latitude (DMS): 28.0 0.0' 1.56" NLongitude (DMS): 82.0 26.0' 59.04" WLatitude (DD): 28.000433333333334Longitude (DD): -82.44973333333334Coordinates - Image 1---------------------Latitude (DMS): 28.0 0.0' 1.54" NLongitude (DMS): 82.0 26.0' 58.75" WLatitude (DD): 28.000427777777777Longitude (DD): -82.44965277777779

Отображение местоположения фотографий на карте

Вы, вероятно, не знаете широту и долготу своего дома, даже если округлить до ближайшего градуса. Есть несколько простых способов преобразовать данные о местоположении EXIF во что-то более лёгкое для понимания.

Один из способов использовать встроенный в Python модуль webbrowser для открытия новой вкладки браузера для каждой фотографии, используя десятичную версию EXIF-координат каждой фотографии в качестве параметров URL-адреса Google Maps. Мы создадим служебную функцию с именем draw_map_for_location(), которая сделает следующее:

def draw_map_for_location(latitude, latitude_ref, longitude, longitude_ref):    import webbrowser        decimal_latitude = dms_coordinates_to_dd_coordinates(latitude, latitude_ref)    decimal_longitude = dms_coordinates_to_dd_coordinates(longitude, longitude_ref)    url = f"https://www.google.com/maps?q={decimal_latitude},{decimal_longitude}"    webbrowser.open_new_tab(url)for index, image in enumerate(images):    draw_map_for_location(image.gps_latitude,                           image.gps_latitude_ref,                           image.gps_longitude,                          image.gps_longitude_ref)

Когда вы запустите его, откроются две новые вкладки браузера, на каждой из которых будет отображаться карта Google, указывающая, где была сделана соответствующая фотография.

Отображение города, региона и страны, где был сделан снимок

Другой способ отобразить местоположение фотографии использовать обратное геокодирование, то есть процесс преобразования географических координат в адрес или название места. Для этого нам нужно установить два модуля Python:

  • reverse_geocoder простой автономный обратный геокодер, который использует внутренние таблицы для преобразования набора координат в набор названий городов и штатов/провинций и кодов стран. Установите его, введя pip install reverse_geocoder в командной строке.

  • pycountry утилита поиска стран, которую мы будем использовать для преобразования кодов стран в их соответствующие названия. Установите это, введя pip install pycountry в командной строке.

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

import reverse_geocoder as rgimport pycountryfor index, image in enumerate(images):    print(f"Location info - Image {index}")    print("-----------------------")    decimal_latitude = dms_coordinates_to_dd_coordinates(image.gps_latitude, image.gps_latitude_ref)    decimal_longitude = dms_coordinates_to_dd_coordinates(image.gps_longitude, image.gps_longitude_ref)    coordinates = (decimal_latitude, decimal_longitude)    location_info = rg.search(coordinates)[0]    location_info['country'] = pycountry.countries.get(alpha_2=location_info['cc'])    print(f"{location_info}\n")

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

  • Название города, посёлка или деревни.

  • Главный административный регион, который обычно представляет собой штат или провинцию.

  • Незначительный административный район, который обычно является округом или районом.

  • Код страны.

Затем он использует метод get() из pycountry для преобразования кода страны, предоставленного reverse_geocoder, в кортеж, содержащий соответствующие общие и официальные названия стран.

Вот его результат:

Location info - Image 0-----------------------{'lat': '27.94752', 'lon': '-82.45843', 'name': 'Tampa', 'admin1': 'Florida', 'admin2': 'Hillsborough County', 'cc': 'US', 'country': Country(alpha_2='US', alpha_3='USA', name='United States', numeric='840', official_name='United States of America')}Location info - Image 1-----------------------{'lat': '27.94752', 'lon': '-82.45843', 'name': 'Tampa', 'admin1': 'Florida', 'admin2': 'Hillsborough County', 'cc': 'US', 'country': Country(alpha_2='US', alpha_3='USA', name='United States', numeric='840', official_name='United States of America')}

Другая полезная информация о датчиках

Как я уже упоминал в начале этой статьи, смартфоны снабжены датчиками. К ним относятся магнитометр, барометр и акселерометр. В сочетании с GPS эти датчики предоставляют дополнительную информацию, которая добавляется к метаданным EXIF каждой фотографии.

В каком направлении была обращена камера?

Магнитометр воспринимает магнитные поля, в том числе создаваемые Землёй. Его основная цель быть компасом телефона и определять направление, на которое он указывает. Эта информация записывается в EXIF в виде компасного курса каждый раз, когда вы делаете снимок.

Давайте определим, в каком направлении я смотрел, когда делал каждую из этих фотографий:


Мы будем использовать следующие свойства exif-Image, чтобы определить направление, в котором была направлена камера:

  • gps_img_direction: направление по компасу, то есть направление, в котором смотрела камера, когда был сделан снимок, выраженный в десятичных градусах. 0 север, 90 восток, 180 юг и 270 запад.

  • gps_img_direction_ref: контрольная точка для gps_img_direction. Это может быть либо T, что означает, что 0 относится к истинному или географическому северу, либо M, что означает, что 0 относится к магнитному северу. В большинстве случаев используется истинный север.

В приведённом ниже коде показано направление камеры для четырёх фотографий озера. Он использует несколько служебных функций:

  • degrees_to_direction(): эта функция преобразует направления по компасу в основные направления (например, N, NE, NNE и т. д.);

  • format_direction_ref(): эта функция превращает значение в gps_img_direction_ref понятную для человека строку.

def degrees_to_direction(degrees):    COMPASS_DIRECTIONS = [        "N",        "NNE",        "NE",        "ENE",        "E",         "ESE",         "SE",         "SSE",        "S",         "SSW",         "SW",         "WSW",         "W",         "WNW",         "NW",         "NNW"    ]        compass_directions_count = len(COMPASS_DIRECTIONS)    compass_direction_arc = 360 / compass_directions_count    return COMPASS_DIRECTIONS[int(degrees / compass_direction_arc) % compass_directions_count]def format_direction_ref(direction_ref):    direction_ref_text = "(true or magnetic north not specified)"    if direction_ref == "T":        direction_ref_text = "True north"    elif direction_ref == "M":        direction_ref_text = "Magnetic north"    return direction_ref_text# Import imageslake_images = []for i in range(1, 5):    filename = f"lake {i}.jpg"    with open(f"./images/{filename}", "rb") as current_file:        lake_images.append(Image(current_file))# Display camera direction for each imagefor index, image in enumerate(lake_images):    print(f"Image direction - Image {index}")    print("-------------------------")    print(f"Image direction: {degrees_to_direction(image.gps_img_direction)} ({image.gps_img_direction})")    print(f"Image direction ref: {format_direction_ref(image.gps_img_direction_ref)}\n")

Когда вы запустите код, вы увидите следующий результат:

Image direction - Image 0-------------------------Image direction: ENE (78.416259765625)Image direction ref: True northImage direction - Image 1-------------------------Image direction: N (1.174224853515625)Image direction ref: True northImage direction - Image 2-------------------------Image direction: SSE (178.46739196870607)Image direction ref: True northImage direction - Image 3-------------------------Image direction: W (273.8248136315229)Image direction ref: True north

На какой высоте был сделан снимок?

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

Давайте выясним, на каких высотах были сделаны эти фотографии:

Мы воспользуемся этими свойствами объекта Exif Image для определения высоты:

  • gps_altitude: высота в метрах;

  • gps_altitude_ref: контрольная точка для gps_altitude. Это значение равно 0, что означает, что значение в gps_altitude относится к метрам над уровнем моря, или 1, что означает, что значение в gps_altitude относится к метрам ниже уровня моря.

Следующий код отображает высоту, сообщённую телефоном в момент съёмки каждой из фотографий. Он использует одну служебную функцию, format_altitude(), которая определяет, находится ли заданная высота над или под уровнем моря:

def format_altitude(altitude, altitude_ref):    altitude_ref_text = "(above or below sea level not specified)"    if altitude_ref == 0:        altitude_ref_text = "above sea level"    elif altitude_ref == 1:        altitude_ref_text = "below sea level"    return f"{altitude} meters {altitude_ref_text}"# Import imagesaltitude_images = []for i in range(1, 3):    filename = f"altitude {i}.jpg"    with open(f"./images/{filename}", "rb") as current_file:        altitude_images.append(Image(current_file))        # Display camera altitude for each imagefor index, image in enumerate(altitude_images):    print(f"Altitude - Image {index}")    print( "------------------")    print(f"{format_altitude(image.gps_altitude, image.gps_altitude_ref)}\n")

Вот результат:

Altitude - Image 0------------------14.025835763206075 meters above sea levelAltitude - Image 1------------------359.13079847908745 meters above sea level

Я мог бы сказать вам, где я сделал эти фотографии, но вы уже знаете, как это выяснить.

Двигался ли фотограф?

Смартфоны используют комбинацию местоположений GPS с течением времени и акселерометра, чтобы определить скорость телефона и направление, в котором он движется. Некоторые телефоны предоставляют эту информацию как часть метаданных EXIF на фотографиях.

Мой Motorola One Hyper не записывает метаданные, связанные со скоростью, но мой iPhone это делает. Доступ к этим данным можно получить с помощью этих двух методов объекта exif Image:

  • gps_speed: скорость, выраженная в виде числа;

  • gps_speed_ref: единицы скорости, используемые для значения в gps_speed. Это значение может быть: K для километров в час; M для миль в час; N для морских миль в час, или узлов.

Рассмотрим следующие фото:

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

def format_speed_ref(speed_ref):    speed_ref_text = "(speed units not specified)"    if speed_ref == "K":        speed_ref_text = "km/h"    elif speed_ref == "M":        speed_ref_text = "mph"    elif speed_ref == "N":        speed_ref_text = "knots"    return speed_ref_text# Import imagesspeed_images = []for i in range(1, 4):    filename = f"speed {i}.jpg"    with open(f"./images/speed {i}.jpg", "rb") as current_file:        speed_images.append(Image(current_file))    for index, image in enumerate(speed_images):    print(f"Speed - Image {index}")    print("---------------")    print(f"Speed: {image.gps_speed} {format_speed_ref(image.gps_speed_ref)}\n")

Вот результат:

Speed - Image 0---------------Speed: 0.0 km/hSpeed - Image 1---------------Speed: 20.19736291335287 km/hSpeed - Image 2---------------Speed: 5.520932607215793 km/h

Редактирование EXIF данных и их сохранение

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

Редактирование координат фотографии

Начнём с этой фотографии:

К настоящему времени вы должны знать, как читать координаты из EXIF и использовать эти координаты, чтобы открыть карту Google, чтобы показать местоположение, где фото снято.

Вот код, который это сделает. Он использует служебную функцию draw_map_for_location(), которую мы определили ранее:

with open(f"./images/hotel original.jpg", "rb") as hotel_file:    hotel_image = Image(hotel_file)    # Read the GPS dataprint("Original coordinates")print("--------------------")print(f"Latitude: {hotel_image.gps_latitude} {hotel_image.gps_latitude_ref}")print(f"Longitude: {hotel_image.gps_longitude} {hotel_image.gps_longitude_ref}\n")# Open a Google Map showing the location represented by these coordinatesdraw_map_for_location(hotel_image.gps_latitude,                      hotel_image.gps_latitude_ref,                      hotel_image.gps_longitude,                      hotel_image.gps_longitude_ref

Он выводит следующее:

Original coordinates--------------------Latitude: (28.0, 21.0, 58.44) NLongitude: (81.0, 33.0, 34.29) W

Кроме того, он открывает новую вкладку браузера, показывающую карту Google, которая отображает отели Swan и Dolphin, которые находятся в нескольких минутах ходьбы от Walt Disney World во Флориде.

Давайте сделаем вещи немного интереснее, изменив координаты, встроенные в данные EXIF фотографии, чтобы они сообщали, что она была сделана в Зоне 51. Если вы не слышали об этом месте, это военный объект в Неваде, в котором, как считают теоретики теории заговора, правительство США хранит тела пришельцев и космический корабль, захваченные в 1950-х годах. Его координаты: 37,0 14 '3,6 "северной широты, 115 48' 23,99" западной долготы.

Вы видели, что чтение значения тега EXIF с использованием объекта Exif Image это просто чтение значения в соответствующем свойстве. Точно так же редактирование его значения это просто вопрос присвоения нового значения этому свойству. В этом случае мы присвоим значения, определяющие координаты Зоны 51, свойствам изображения gps_latitude, gps_latitude_ref, gps_longitude и gps_longitude_ref:

# Boring. Let's change those coordinates to Area 51!hotel_image.gps_latitude = (37.0, 14, 3.6)hotel_image.gps_latitude_ref = 'N'hotel_image.gps_longitude = (115, 48, 23.99)hotel_image.gps_longitude_ref = 'W'# Read the revised GPS dataprint("Revised coordinates")print("-------------------")print(f"Latitude: {hotel_image.gps_latitude} {hotel_image.gps_latitude_ref}")print(f"Longitude: {hotel_image.gps_longitude} {hotel_image.gps_longitude_ref}\n")# Open a Google Map showing the location represented by the revised coordinatesdraw_map_for_location(hotel_image.gps_latitude,                      hotel_image.gps_latitude_ref,                      hotel_image.gps_longitude,                      hotel_image.gps_longitude_ref

Выполнение кода приведёт к следующему результату

Revised coordinates-------------------Latitude: (37.0, 14.0, 3.6) NLongitude: (115.0, 48.0, 23.99) W

... и он откроет новую вкладку с картой Google, в которой отображается Зона 51.

Заполнение неиспользуемых тегов EXIF

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

Примечание: модуль exif записывает только теги в спецификации EXIF, но не дополнительные теги, включённые поставщиками. Официальные теги в спецификации EXIF подчёркнуты.

Вы можете присвоить значение тегу вне спецификации EXIF, даже тегу, который вы создали. Объект Image будет хранить это значение, но только до тех пор, пока объект остаётся в памяти. Вы не сможете сохранять теги, отличные от EXIF, или их значения, потому что метод, преобразующий данные в объекте Image для записи в файл, учитывает только стандартные теги EXIF.

Вот несколько тегов EXIF, которые вы, возможно, захотите заполнить, так как они удобны для управления библиотекой фотографий. Они оба принимают строковые значения:

  • ImageDescription: описание фотографии. В объектах Exif Image это отображается как свойство image_description.

  • Copyright: уведомление об авторских правах на фотографию. В объектах Exif Image это свойство copyright.

Вот код, который заполняет эти теги:

hotel_image.image_description = "The Dolphin Hotel in Orlando, viewed at sunset from the Swan Hotel"hotel_image.copyright = "Copyright 2021 (Your name here)"print(f"Description: {hotel_image.image_description}")print(f"Copyright: {hotel_image.copyright}")

Выполнение кода даёт следующий результат:

Description: The Dolphin Hotel in Orlando, viewed at sunset from the Swan HotelCopyright: Copyright 2021 (Your name here)

Сохранение фото с обновленными данными

Теперь, когда мы отредактировали данные EXIF на картинке, давайте сохраним их как новый файл с названием hotel_updated.jpg.

with open('./images/hotel updated.jpg', 'wb') as updated_hotel_file:    updated_hotel_file.write(hotel_image.get_file())

Этот код создаёт файловый объект updated_hotel_file для записи двоичных данных в файл с именем hotel_updated.jpg. Затем он использует метод Image get_file() для получения данных об изображении отеля в сериализуемой форме и записывает эти данные в файл.

Теперь у вас должен быть новый файл: hotel_updated.jpg. Загрузим его и убедимся, что изменённые и добавленные данные сохранены:

with open(f"./images/hotel updated.jpg", "rb") as hotel_file:    hotel_image = Image(hotel_file)    print("Coordinates")print("-----------")print(f"Latitude: {hotel_image.gps_latitude} {hotel_image.gps_latitude_ref}")print(f"Longitude: {hotel_image.gps_longitude} {hotel_image.gps_longitude_ref}\n")print("Other info")print("----------")print(f"Description: {hotel_image.image_description}")print(f"Copyright: {hotel_image.copyright}")# Open a Google Map showing the location represented by these coordinatesdraw_map_for_location(hotel_image.gps_latitude,                      hotel_image.gps_latitude_ref,                      hotel_image.gps_longitude,                      hotel_image.gps_longitude_ref

Код выдаст вам этот результат

Coordinates-----------Latitude: (37.0, 14.0, 3.6) NLongitude: (115.0, 48.0, 23.99) WOther info----------Description: The Dolphin Hotel in Orlando, viewed at sunset from the Swan HotelCopyright: Copyright 2021 (Your name here)

... и откроется ещё одна вкладка браузера, отображающая Зону 51 на карте.

Удаление данных EXIF и сохранение очищенной фотографии

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

Первый способ использовать метод delete(), предоставляемый объектом Exif-Image. Давайте используем его, чтобы удалить данные о широте:

hotel_image.delete('gps_latitude')hotel_image.delete('gps_latitude_ref')print("Latitude data")print("-------------")print(f"gps_latitude: {hotel_image.get('gps_latitude', 'Not found')}")print(f"gps_latitude_ref: {hotel_image.get('gps_latitude_ref', 'Not found')}")

Вот результат кода выше:

Latitude data-------------gps_latitude: Not foundgps_latitude_ref: Not found

Второй способ использовать оператор Python del, который удаляет объекты из памяти. В этом случае мы будем использовать его для удаления атрибутов hotel_image, в которых хранятся данные о долготе:

del hotel_image.gps_longitudedel hotel_image.gps_longitude_refprint("Longitude data")print("--------------")print(f"gps_longitude: {hotel_image.get('gps_longitude', 'Not found')}")print(f"gps_longitude_ref: {hotel_image.get('gps_longitude_ref', 'Not found')}")

Вот результат кода выше:

Longitude data--------------gps_longitude: Not foundgps_longitude_ref: Not found

Теперь, когда мы удалили данные о местоположении с фотографии, давайте сохраним её под новым именем, hotel_without_location_data.jpg:

with open('./images/hotel without location data.jpg', 'wb') as updated_hotel_file:    updated_hotel_file.write(hotel_image.get_file())

Наконец, если вы хотите просто удалить все данные EXIF с фотографии, вы можете использовать метод delete_all() объекта exif Image:

hotel_image.delete_all()dir(hotel_image)
['<unknown EXIF tag 322>', '<unknown EXIF tag 323>', '_segments', 'delete', 'delete_all', 'get', 'get_file', 'get_thumbnail', 'has_exif']

Опять же, как только вы использовали delete_all() для удаления всех тегов EXIF, вам нужно сохранить эти изменения. Приведённый ниже код сохраняет наше изображение со всеми удалёнными тегами как hotel_without_tags.jpg:

with open('./images/hotel without tags.jpg', 'wb') as updated_hotel_file:    updated_hotel_file.write(hotel_image.get_file())

Практические и технические соображения

Причины удаления метаданных EXIF

Метаданные EXIF добавляют к цифровым фотографиям совершенно новый уровень информации и ряд вещей, которые необходимо учитывать пользователям, разработчикам и организациям.

Одно из очевидных соображений это конфиденциальность. Метаданные GPS для отдельной фотографии могут определить ваше местоположение в определённую дату и время. Что гораздо более ценно, так это совокупный GPS из чьей-то камеры, поскольку он содержит шаблоны, которые можно проанализировать, чтобы определить, где вы живёте, работаете и какие места вы часто посещаете в повседневной жизни. Вот почему более авторитетные социальные сети удаляют эту информацию, когда вы публикуете свои фотографии в Интернете. Помните, что это означает лишь то, что ваши фотографии в галерее социальной сети не содержат данных GPS. Нет гарантии, что служба не записала информацию о местоположении чтобы передать её рекламодателю перед её удалением.

Другие метаданные EXIF, такие как марка, модель, настройки и даже ориентация камеры, могут использоваться для связывания набора фотографий с конкретным человеком.

Некоторые фотографы больше озабочены секретностью, чем конфиденциальностью, когда речь идёт о метаданных их фотографий. Они не хотят разглашать настройки камеры, которые использовали для фотосъёмки.

Причины редактирования или добавления метаданных EXIF

Одна из первоначальных причин, по которой был разработан формат метаданных EXIF, заключалась в том, чтобы упростить автоматизацию процесса каталогизации, сортировки и поиска в коллекции цифровых фотографий. EXIF позволяет искать фотографии, сделанные в течение определенного периода, с помощью определённого устройства или в определённом месте. Другие теги, такие как тег copyright, позволяют искать фотографии, сделанные определённым фотографом, а также защищать его авторские права.

Хотя тег ImageDescription был предназначен для хранения описания изображения, вы также можете использовать его для хранения другой полезной текстовой информации, связанной с фотографией, например тегов для классификации изображения или инструкций по обработке и редактированию фотографии.

Метаданные EXIF особенно полезны в мобильных приложениях, которые записывают одновременные комбинации визуальной информации, информации о дате/времени и местоположении. Например, от техника может потребоваться сделать фотографии выполненных ремонтных работ до и после с указанием того, где, когда и как были выполнены эти работы.

Другие вещи, которые следует учитывать

Как мы видели в различных тегах, записанных устройствами iPhone и Android, используемыми для фотосъёмки в этой статье, разные камеры записывают разные наборы тегов EXIF. Программное обеспечение для редактирования фотографий часто записывает информацию в разные теги или добавляет свои собственные теги. Эти дополнительные метаданные часто могут указывать на то, что фотография была отредактирована.

В фотографии дикой природы существует концепция Ethical EXIF, которая описывает этические стандарты, которым следует придерживаться при съёмке. Он включает такую информацию, как состояние здоровья и уровень стресса животного на фотографии, как долго животное находилось в неволе и было ли животное вывезено из среды обитания для фотографии.

Наконец, есть сообщения, которые отображаются в мобильных приложениях, использующих камеру, при первом использовании. Обычно они говорят что-то вроде Это приложение использует камеру. Вы согласны? , Но большинство из них не даёт понять, что камера добавляет местоположение и другие метаданные к каждой сделанной фотографии. Если вы пишете мобильные приложения, использующие камеру, вы можете сообщить об этом пользователю.

Знание Python это полезный hard skill не только для программиста, но и для аналитика и даже маркетолога. С ним вы можете сами написать простой парсер, написать небольшое приложение под свои задачи и даже увеличить свой доход, выполняя заказы на фрилансе. Если вы хотите дополнительно прокачать себя и освоить этот язык под чутким руководством наших опытных менторов обратите внимание на курс Fullstack-разработчик на Python и Python для веб-разработки.

Узнайте, как прокачаться в других специальностях или освоить их с нуля:

Другие профессии и курсы
Подробнее..

Разум vs Интуиция или как принимать решения

02.04.2021 14:12:19 | Автор: admin

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

Перед принятием решения - загляни в будущее

В процессе принятия решения, по моему убеждению, участвуют две составляющие Разум и Интуиция.

Разум

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

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

- Ах если бы мы знали, что так произойдет!
- Кто же мог знать, что так будет!?
- Черный лебедь!

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

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

Интуиция

А как узнать будущее? Будущее никому неизвестно. Будущее, пока оно не наступило неизвестно. Однако в мире есть такое понятие как тенденции. Например, если человек употребляет алкоголь в больших количествах, то тенденция такова, что он умрет от цирроза печени. Хотя человек может умереть и от несчастного случая, но и вероятность летального исхода от болезни печени растет с каждым днем.

Также и события, которые окружают нас имеют ту или иную вероятность реализоваться в действительности. Если Аннушка уже разлила масло, то вероятность, что голова Берлиоза покатится по Патриаршим велика.

И вот вопрос, наделил ли нас Господь Бог таким чувством, которое может улавливать незаметные дуновения распределения вероятностей грядущих событий? Ответ - Да! Имя этому чувству Интуиция. Именно Интуиция ответственна за получение информации о грядущих событиях. Оставим пока в стороне откуда и как Интуиция получает эту информацию. Это тема отельной стати. Здесь для нас будет достаточным только признание двух фактов нашей жизни. Факта того, что вероятность событий влияет на их реализацию в материальном мире. И факта того, что человек может улавливать эти вероятности и интерпретировать их на сознательном уровне.

Форма чувства

Итак, Интуиция это чувство. Знание, которое мы получаем из Интуиции доступно нам в виде образов, на уровне чувств. Мы чувствуем. Далее эти знания, полученные на уровне чувств, требуется переложить на уровень Разума. Придать чувствам формы, характеристики, описания с той целью, чтобы наш Разум имел возможность оперировать с чувствами как с фактами.

Как мы видим, чтобы вытащить на свет Божий знания о грядущем требуется две вещи: умение чувствовать грядущие события, а также умение корректно интерпретировать свои чувства в правильные формы нашего Разума. Если мы ничего не чувствам, то работать не будет. Если мы чувствуем, но не можем правильно описать, сформулировать свои чувства, то работать тоже не будет.

Если мы имеем достаточный жизненный опыт, то чуйка (Интуиция) автоматически трансформируется в нашем сознании в правильные словоформы, и мы работаем с чувствами как с достоверным знанием. Но это приходит с опытом. Просто надо чаще обращать на это внимание и не считать это сверхъестественным. Это одна из сторон нашей жизни и этим надо уметь пользоваться. Как в свое время человек поставил себе на службу свой Разум, так и сейчас человек должен поставить себе на службу свою Интуицию.

Коварство чувства

На уровне чувств мы полностью работаем с самими собою. Чувства субъективны. Объект исследования является в одно и тоже время исследуемым и исследователем. Субъект познает самого себя посредством самого себя. Врач врачует себя сам. Разумеется, что при такой методике исследования имеется огромный потенциал для ошибок, т.к. нет ориентиров, нет внешнего знания, с которым можно было соотнести полученные данные. При изучении самого себя, при познании самого себя, приходится быть особенно дисциплинированным исследователем. Вероятность обмануть себя велика. И, как всегда, для выявления истинного знания нам помогает реальность. Только проверяя свои догадки в реальности, мы можем получить ответ верно ли наше суждение или нет. Верить себе или нет.

Например, мы можем выдать желаемое чувство за работу нашей Интуиции. В то время как это чувство будет, по сути, только наводкой, индуцированной нами. Если принять это ошибочное чувство за Интуицию очень скоро реальность покажет нам, что мы ошибались. Так, путем проб и ошибок мы учимся работать на уровне Интуиции. Учимся отделять свои желания и чувства от собственно Божественной Интуиции.

Что важнее Разум или Интуиция?

Одним из особенностей человека является стремление все генерализировать и упрощать. Либо всё белое, либо всё чёрное. Никаких оттенков, никаких компромиссов! Что поделать. Так нам проще. Так нам удобнее жить в нашей действительности. Этот коммунист, этот либерал, этот баянист и т.д. Однако жизнь многообразна в своих проявлениях и в своих пропорциях.

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

Поэтому и в вопросе первенства Разума и Интуиции нельзя выделить важный и неважный компонент. Оба компонента важны, но в правильной пропорции. При этом правильная пропорция, правильное соотношение Разума и Интуиции для каждого случая свои. Соотношение это динамическое для каждого конкретного случая. Для каждого "супа" своя порция "соли".

Крайности

Если вдаваться в крайности, то мы увидим извращения. Слушая только Разум и полное игнорирование Интуиции приводит к ситуациям, которые принято называть "Черным лебедем":

- Кто же знал!?
- Кто же мог подумать!?

Например, все животные задолго до землетрясения или цунами покидают район бедствия и выживают. В то время как человек игнорируя свою Интуицию продолжает находится в опасном месте до тех пор, пока его не накроет.

Другая крайность. Отрицание Разума и жизнь только на основе чувств и Интуиции. Здесь мы впадаем в транс жизни и ожидаем некоего чуда, которое должно с нами произойти само по себе. Мы не деятельны, мы все отдаём на волю случая. Дни текут одни за одним, а в нашей жизни ничего не происходит. Дополнительно усугубляет ситуацию то, что мы начинаем ошибочно выдавать наши желания за действия Интуиции. Ведь наши желания и образы также работают на чувственном уровне и их очень легко спутать с Интуицией. Мы выдаем за Интуицию те чувства, которые, по сути, Интуицией не являются. Мы становимся бесхребетными, вялыми, недеятельными, безвольными созданиями, живущими по наитию в ожидании чуда.

Как видим, крайности опасны. Успех в том, чтобы найти правильное соотношение Разума и Интуиции в своей жизни для каждого конкретного случая.

При чём тут стартап?

Стартап дело рискованное. Можно потратить все свои деньги, время, здоровье, силы и "выстрелить в пустоту". В стартапе никто не гарантирует вам успеха. Вы являетесь первопроходцем. Риски максимальные. Поэтому, чтобы немного повысить вероятность успеха вам будет полезно прислушаться к голосу Интуиции.

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

О своём опыте стартапа я писал в этой статье.

Зрячий

Позволю себе привести аналогию со зрением. Давайте представим, что люди не обладают способностью видеть, допустим все люди слепы. Тогда появление зрячего человека считается чудом. Зрячий человек имеет дополнительное конкурентное преимущество по сравнению с незрячим. Аналогично и с работой Интуиции. Умение работать на уровне Интуиции предоставляет человеку значительные конкурентные преимущества. Человек видит (чувствует) то, чего другие не видят. Поэтому так важно развивать в себе это чувство, наравне с другими чувствами такими, как зрение, слух, обоняние, осязание и другими.

Шестое чувство спасает жизнь

Из мемуаров ветеранов Великой Отечественной Войны мы узнаём, что фронтовик заранее знал куда упадет снаряд, и где пролетит пуля. На войне в условиях выживания все чувства обостряются и нацелены только на одну задачу выжить. Смерть на войне подстерегает тебя повсеместно, ежесекундно. Знание о том куда летит пуля, где засада, спало жизнь тем, кто умел уловить это знание из океана бесконечных вероятностей грядущих событий. За время войны произошел некий естественный отбор популяции. За четыре года до конца войны дошли в большей степени те фронтовики, которые умели слушать свою Интуицию и незамедлительно реагировать на её подсказки. Поэтому Интуиция у нас в крови, как у потомков тех, кто прошел естественный отбор ужасной бойни ХХ века.

Кстати, совсем не обязательно идти на войну, чтобы начать улавливать едва слышимый голос Интуиции. Для этого достаточно сесть за руль и выехать на дорогу. За рулем водитель также рискует потерять жизнь, как и на войне. В день на дорогах РФ гибнет порядка 100 человек или 30к человек в год. Вокруг нас идет война, которую мы не замечаем или не хотим замечать. Гибнут в основном молодые ребята, как и на войне. К примеру, в Первую Чеченскую за два года боевых действий РФ потеряла порядка 15к молодых ребят. Если сопоставить цифры, то получается, что за один год на дорогах РФ прокатывается две Чеченские войны.

Руль находится в руках водителя. Жизнь в его руках. Каждую секунду водитель принимает решения, которые могут стоить ему жизни.

Дорога - тренажер Интуиции

Кратко

  • При принятии решения надо работать на двух уровнях: на уровне Разума и на уровне Интуиции.

  • Разум оперирует только случившимися фактами Интуиция позволяет получить факты, которые только готовятся материализоваться.

  • Только учитывая факты существующие и факты будущие можно принять адекватное реальности решение.

  • Задача каждого человека научиться чувствовать и оперировать будущими фактами, которые готовятся материализоваться. Не считать это сверхъестественным, а считать одним из проявлений нашей жизни.

  • Успех в правильном сочетании в своей жизни Разума и Интуиции.

  • Для каждой конкретной ситуации сочетание Разума и Интуиции своё.

Итак, принимая решения на базе фактов известных и фактов грядущих, у нас больше шансов принять более адекватное реальности решение.

Успехов в делах и на дорогах!

Подробнее..

Извлечь максимум из новостей в интернете, часть 1

04.04.2021 22:19:50 | Автор: admin

Извлечь максимум из новостей в интернете

Навеяно статьей Почему я по-прежнему пользуюсь RSS

Я сам очень активно использую формат новостей, чем и хотел бы поделиться с сообществом.

Будут скриншоты и, возможно, немного избыточных пояснений.

Будут следующие части:

  1. Часть 1:

  • Какую информацию я вообще потребляю через новости;

  • Чтение программами (rss-агрегаторами) - что использую лично я;

  • Форматы RSS и Atom, как их можно обрабатывать программами на локальном компьютере;

  1. Часть 2:

  • Автоматизаторы (zapier, ifttt);

  1. Часть 3:

  • Как я автоматизировал доставку аудио-подкастов на свой плеер.

Часть 1

Какую информацию я вообще потребляю с помощью новостей

Раньше, когда я много времени проводил в метро по пути на работу и обратно, то загружал новости в свой планшет и потом, уже без интернета спокойно читал то, что было интересно (не все помнят, но интернет в метро был не всегда!). Например, баш и ЖЖ поставляют контент в формате RSS. Новости со всего мира от лента.ру есть в формате RSS. Поговаривают, что в древние времена и твиттер можно было читать через ленту новостей в формате RSS! Но потом пришли жадные менеджеры и сказали, что так они не получат много денег, поэтому RSS исчез из твиттера.

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

Потом обнаружил, что многие другие, интересные мне темы (например, аудиоподкасты) тоже можно отслеживать через ленту новостей. Вот, например, Радио Маяк.

Чтение программами (rss-агрегаторами)

Чтобы читать новости на планшете, можно использовать любую подходящую программу. Благо, их очень много - для Андроида, для Apple и для десктопов.

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

Для десктопа я раньше использовал RSS Owl:

RSS OwlRSS Owl

А потом с удивлением открыл для себя продукт от JetBrains: OMEA Reader:

JetBrains OMEA ReaderJetBrains OMEA Reader

Функционал у продукта JetBrains просто космический, поэтому как только я на него перешёл, то уже и не уходил:

  • можно ставить комментарии к новостям

  • можно фильтровать новости и по отборам назначать тэги, выделять цветом или выдавать оповещения на экране

  • иерархическая группировка лент новостей

  • и многое-многое другое.

Форматы RSS и Atom, как их можно обрабатывать программами на локальном компьютере

Новости, по сути - это простой xml-файл. Есть формат RSS (очень старый формат, непонятно кто его поддерживает и будет ли он развиваться). Мне он не очень нравится:

  • из-за формата дат - <pubDate>Sun, 28 May 2017 09:00:00 GMT</pubDate>, что затрудняло для меня автоматическую обработку

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

На замену RSS фирма Google придумала свой формат - Atom, и вроде бы даже поддерживает его.

Файлы из интернета, в том числе и новости, можно читать с помощью curl, wget и (почему-бы и нет?) с помощью Power-shell.

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

Curl:

chcp 65001    curl ^    --header "user-agent: cURL automated task" ^    --output "%TEMP%\updates.xml" ^    "https://news.webits.1c.ru/news/Updates/atom"

Если на компьютере включен Антивирус Касперского, то можно получить ошибку curl: (35) schannel: next InitializeSecurityContext failed: Unknown error (0x80092012) - Функция отзыва не смогла произвести проверку отзыва для сертификата. Я просто отключил антивирус на 5 минут.

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

Power-shell:

# file: Get-News-001.ps1  Clear-Host    $webClient = New-Object Net.WebClient  $webClient.UseDefaultCredentials = $true  $webClient.Proxy.Credentials = $webClient.Credentials  $webClient.Headers.Add("user-agent", "PowerShell automated task")    # Подозреваю, что из-за того, что данные передаются без BOM, то получение данных  # через DownloadString с последующим выводом выдаст на экран кракозябры.  # Поэтому в явном виде преобразуем в UTF8  $newsData = $webClient.DownloadData("https://news.webits.1c.ru/news/Updates/atom")    Write-Host ([System.Text.Encoding]::UTF8).GetString($newsData)

Не забываем, что в power-shell надо включить возможность запуска неподписанных макросов. Это делается или в настройках вашей IDE, или прямо в командной строке, параметром -ExecutionPolicy=RemoteSigned

powershell -file "Get-News-001.ps1" -ExecutionPolicy=RemoteSigned

Что нам это даст? Пока ничего интересного. Но так как новости - это структурированный текст в формате xml, почему-бы не обработать его? Например, найти новость по значению какой-нибудь категории?

Найдём в новостях от 1С новости со значениями категорий Вид новости обновления=Публикация новой версии и Продукт=Комплексная автоматизация

Пример кода:

# file: Get-News-002.ps1Clear-Host# Настройки отбора, в виде массива$CategoryProducts = @(    # "Продукт=1С:Библиотека стандартных подсистем", # Заполнить!    "Продукт=Комплексная автоматизация" # Заполнить!)$CategoryNewsTypes = @(    "Вид новости обновлений=Публикация новой версии")$webClient = New-Object Net.WebClient$webClient.UseDefaultCredentials = $true$webClient.Proxy.Credentials = $webClient.Credentials$webClient.Headers.Add("user-agent", "PowerShell automated task")# Т.к. данные без BOM, то лучше явно преобразовать.$newsData = $webClient.DownloadData("https://news.webits.1c.ru/news/Updates/atom")[xml]$news = ([System.Text.Encoding]::UTF8).GetString($newsData)#[xml]$news = Get-Content -Encoding UTF8 -LiteralPath "$($env:TEMP)\updates.xml"for($c1=0;$c1 -lt $news.feed.entry.Count;$c1++){    # Получим новость    $entry = $news.feed.entry[$c1]    $ProductName    = ""    $bFoundProduct  = $false    $bFoundNewsType = $false    for($c2=0;$c2 -lt $entry.category.Count;$c2++){        # Получим и проверим категории новости        $CategoryProducts | ForEach-Object {            if($entry.category[$c2].term -eq $_){                $ProductName = $entry.category[$c2].term                $bFoundProduct = $true            }        }        $CategoryNewsTypes | ForEach-Object {            if($entry.category[$c2].term -eq $_){                $bFoundNewsType = $true            }        }    }    if ($bFoundProduct -and $bFoundNewsType) {        Write-Host ("Найдена подходящая новость. УИН: {0}, Заголовок: {1}" -f ($entry.id, $entry.title))    }}

Уже интереснее. А что мы можем сделать, если нашли нужную категорию? Например, можно самому себе отправить письмо.

Напишем код сразу так, чтобы письмо о выходе новости не отправлялось несколько раз - в отдельном файлике будем хранить entry.id - уникальный идентификатор новости и дату отправки.

# file: Get-News-003.ps1Clear-Host# Файл с информацией об отправленных email.$sendedEmailsPath = "$($env:TEMP)\sended.csv" # Заполнить!if(Test-Path $sendedEmailsPath){    # Файл существует} else {    # Файла не существует - создать пустой файл    Add-Content -LiteralPath $sendedEmailsPath -Encoding UTF8 -Force -Value ""}$sendedEmails = Get-Content -LiteralPath $sendedEmailsPath -Encoding UTF8 -Force# Настройки почты$CurrentDate        = Get-Date $CurrentDate_String = Get-Date -Format "yyyy-MM-dd HH:mm:ss"$From               = "news_center_tester@mail.ru" # Заполнить!$To                 = "old-coder-75@mail.ru" # Заполнить!$EncodingUTF8       = [System.Text.Encoding]::UTF8$UserName           = "news_center_tester" # Заполнить!$Password           = "*****" # Заполнить!$Credential         = New-Object -TypeName System.Management.Automation.PSCredential($UserName, (ConvertTo-SecureString $Password -AsPlainText -Force))$SMTPServer         = "smtp.mail.ru" # Заполнить!$SMTPPort           = 587 # Заполнить!# Настройки отбора, в виде массива$CategoryProducts = @(    # "Продукт=1С:Библиотека стандартных подсистем", # Заполнить!    "Продукт=Комплексная автоматизация" # Заполнить!)$CategoryNewsTypes = @(    "Вид новости обновлений=Публикация новой версии")$webClient = New-Object Net.WebClient$webClient.UseDefaultCredentials = $true$webClient.Proxy.Credentials = $webClient.Credentials$webClient.Headers.Add("user-agent", "PowerShell automated task")$newsData = $webClient.DownloadData("https://news.webits.1c.ru/news/Updates/atom")[xml]$news = ([System.Text.Encoding]::UTF8).GetString($newsData)#[xml]$news = Get-Content -Encoding UTF8 -LiteralPath "$($env:TEMP)\updates.xml"for($c1=0;$c1 -lt $news.feed.entry.Count;$c1++){    # Получим новость    $entry = $news.feed.entry[$c1]    $ProductName    = ""    $bFoundProduct  = $false    $bFoundNewsType = $false    for($c2=0;$c2 -lt $entry.category.Count;$c2++){        # Получим и проверим категории новости        $CategoryProducts | ForEach-Object {            if($entry.category[$c2].term -eq $_){                $ProductName = $entry.category[$c2].term                $bFoundProduct = $true            }        }        $CategoryNewsTypes | ForEach-Object {            if($entry.category[$c2].term -eq $_){                $bFoundNewsType = $true            }        }    }    if ($bFoundProduct -and $bFoundNewsType) {           Write-Host ("Найдена подходящая новость. УИН: {0}, Заголовок: {1}" -f ($entry.id, $entry.title))        # Проверим, была ли информация уже отправлена по email?        # Информация об отправке email хранится по каждому id новости в лог-файле $sendedEmailsPath.        $bEmailWasSent = $false        foreach ($sendedEmail in $sendedEmails) {            if ( $sendedEmail.StartsWith($entry.id) ) {                $bEmailWasSent = $true                break            }        }        # По этой новости ещё не создавался email.        if ($bEmailWasSent -eq $false){            Write-Host "По подходящей новости отправляем емейл..."            # Отправить почту            $Subject = $entry.title            $Body = "<h1>Выход новой версии</h1>" + `                "<p>" + `                $entry.summary."#cdata-section" + `                "</p>"            Send-MailMessage `                -From $From `                -To $To `                -Body $Body `                -BodyAsHtml `                -Credential $Credential `                -Encoding $EncodingUTF8 `                -SmtpServer $SMTPServer `                -Subject $Subject `                -Priority High `                -UseSsl `                -Port $SMTPPort `                -Verbose                            # Записать в лог, чтобы повторно не отправлять почту по этой новости            $LogString = $entry.id + ";" + $CurrentDate_String + ";"            Add-Content -LiteralPath $sendedEmailsPath -Encoding UTF8 -Force -Value $LogString        } else {               Write-Host "По подходящей новости уже был отправлен емейл."        }    }}

Хм. Не хочется вызывать скрипт ручками. Было бы неплохо это вызывать регулярно, например каждые 2 часа. Настроим "Планировщик заданий". В окне запуска (Win+R) вызовем "taskschd.msc".

Добавим новое расписание:

Настроим частоту запуска каждые 4 часа (триггер):

Добавим запуск скрипта (Действие):

Путь к программе powershell.exe надо указывать полный. И в аргументах - или полный путь к скрипту в параметре -file, или заполнить Рабочая папка.

Немного тюнинга - не люблю всплывающие окна. А при выполнении задания по расписанию, каждые 4 часа вылезает на весь экран окно выполнения скрипта. Можно запускать код power-shell через SilentCMD или CreateProcessHidden. Правда, на последнюю ругается антивирус, но не сильно.

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

Что ж, надеюсь, что информация оказалась полезной.
С интересом почитаю комментарии.

Остальные главы постараюсь в ближайшее время выложить.

Подробнее..

Перевод Как проверить подлинность банкнот с помощью нейросети

31.03.2021 16:16:13 | Автор: admin

Разработка прогнозной модели нейронной сети для нового набора данных может оказаться сложной задачей.

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

Этот процесс можно использовать для разработки эффективных моделей нейронных сетей для задач классификации и регрессионного прогнозного моделирования.

В этом руководстве вы узнаете, как разработать модель нейронной сети многослойного персептрона для набора данных двоичной классификации банкнот.


После прохождения этого урока вы будете знать:

  • как загрузить и обобщить набор данных о банкноте и использовать результаты, чтобы предложить подготовку данных и конфигурации модели для использования;

  • как изучить динамику обучения простых моделей MLP в наборе данных;

  • как разработать надежные оценки производительности модели, настроить производительность модели и сделать прогнозы на основе новых данных.

Давайте начнём.

Набор данных классификации банкнот

Первый шаг определить и изучить набор данных.

Мы будем работать со стандартным набором данных двоичной классификации Банкнота.

Набор данных банкноты включает в себя прогнозирование подлинности данной банкноты с учётом ряда мер, взятых из фотографии.

Набор данных содержит 1372 строки с 5 числовыми переменными. Это проблема классификации с двумя классами (двоичная классификация).

Ниже представлен список пяти переменных в наборе данных:

  • дисперсия Вейвлет-преобразованного изображения (непрерывная);

  • асимметрия Вейвлет-преобразованного изображения (непрерывная);

  • эксцесс Вейвлет-преобразованного изображения (непрерывный);

  • энтропия изображения (непрерывная);

  • класс (целое число).

Ниже приведён образец первых 5 строк набора данных.

3.6216,8.6661,-2.8073,-0.44699,04.5459,8.1674,-2.4586,-1.4621,03.866,-2.6383,1.9242,0.10645,03.4566,9.5228,-4.0112,-3.5944,00.32924,-4.4552,4.5718,-0.9888,04.3684,9.6718,-3.9606,-3.1625,0...

Вы можете посмотреть весь набор данных здесь:

Мы можем загрузить набор данных как DataFrame pandas прямо из URL-адреса.

Например:

# load the banknote dataset and summarize the shapefrom pandas import read_csv# define the location of the dataseturl = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/banknote_authentication.csv'# load the datasetdf = read_csv(url, header=None)# summarize shapeprint(df.shape)

При выполнении кода набор данных загружается непосредственно из URL-адреса и выводится форма набора данных.

В этом случае мы можем подтвердить, что набор данных имеет 5 переменных (4 входных и одна для вывода) и что набор содержит 1372 строки.

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

Это также предполагает, что использование перекрёстной проверки в k-кратном размере было бы хорошей идеей, потому что она даст более надёжную оценку производительности модели, чем разделение на обучение/тест, и потому что одна модель будет соответствовать секундам, а не часам или дням обучения.

(1372, 5)

Затем мы можем узнать больше о наборе данных, просмотрев сводную статистику и график данных.

# show summary statistics and plots of the banknote datasetfrom pandas import read_csvfrom matplotlib import pyplot# define the location of the dataseturl = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/banknote_authentication.csv'# load the datasetdf = read_csv(url, header=None)# show summary statisticsprint(df.describe())# plot histogramsdf.hist()pyplot.show()

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

Мы видим, что значения различаются в зависимости от средних значений и стандартных отклонений, возможно, перед моделированием потребуется некоторая нормализация или стандартизация.

                 0            1            2            3            4count  1372.000000  1372.000000  1372.000000  1372.000000  1372.000000mean      0.433735     1.922353     1.397627    -1.191657     0.444606std       2.842763     5.869047     4.310030     2.101013     0.497103min      -7.042100   -13.773100    -5.286100    -8.548200     0.00000025%      -1.773000    -1.708200    -1.574975    -2.413450     0.00000050%       0.496180     2.319650     0.616630    -0.586650     0.00000075%       2.821475     6.814625     3.179250     0.394810     1.000000max       6.824800    12.951600    17.927400     2.449500     1.000000

Затем для каждой переменной создаётся гистограмма.

Мы можем видеть, что, возможно, первые две переменные имеют гауссовоподобное распределение, а следующие две входные переменные могут иметь искажённое гауссово распределение или экспоненциальное распределение.

У нас может быть некоторая выгода от использования степенного преобразования для каждой переменной, чтобы сделать распределение вероятностей менее искажённым, что, возможно, улучшит производительность модели.

Теперь, когда мы знакомы с набором данных, давайте посмотрим, как можно разработать модель нейронной сети.

Динамика обучения нейронной сети

Мы разработаем модель многослойного персептрона (MLP) для набора данных, используя TensorFlow.

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

С учётом того, что набор данных невелик, небольшой размер пакета, вероятно, является хорошей идеей, например, 16 или 32 строки. Использование Адамовской версии стохастического градиентного спуска хорошая идея для начала работы, так как она автоматически адаптирует скорость обучения и хорошо работает на большинстве наборов данных.

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

Мы можем сделать это, используя простое разделение данных на обучение/тест и просматривая графики кривых обучения. Это поможет нам понять, переучиваемся мы или недоучиваемся; тогда мы сможем соответствующим образом адаптировать конфигурацию.

Во-первых, мы должны убедиться, что все входные переменные являются значениями с плавающей запятой, и закодировать целевую метку как целочисленные значения 0 и 1.

...# ensure all data are floating point valuesX = X.astype('float32')# encode strings to integery = LabelEncoder().fit_transform(y)

Затем мы можем разделить набор данных на переменные входа и выхода, а затем на наборы для обучения и тестирования 67/33.

...# split into input and output columnsX, y = df.values[:, :-1], df.values[:, -1]# split into train and test datasetsX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33)

Мы можем определить минимальную модель MLP. В этом случае мы будем использовать один скрытый слой с 10 узлами и один выходной слой (выбранный произвольно). Мы будем использовать функцию активации ReLU в скрытом слое и инициализацию веса he_normal, поскольку их совместное использование является хорошей практикой.

Результатом этой модели является активация сигмоида для двоичной классификации, и мы минимизируем двоичную кросс-энтропийную потерю.

...# determine the number of input featuresn_features = X.shape[1]# define modelmodel = Sequential()model.add(Dense(10, activation='relu', kernel_initializer='he_normal', input_shape=(n_features,)))model.add(Dense(1, activation='sigmoid'))# compile the modelmodel.compile(optimizer='adam', loss='binary_crossentropy')

Мы подгоним модель для 50 тренировочных эпох (выбранных произвольно) с размером пакета 32, потому что это небольшой набор данных.

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

...# fit the modelhistory = model.fit(X_train, y_train, epochs=50, batch_size=32, verbose=0, validation_data=(X_test,y_test))

В конце обучения мы оценим производительность модели на тестовом наборе данных и выведем производительность как точность классификации.

...# predict test setyhat = model.predict_classes(X_test)# evaluate predictionsscore = accuracy_score(y_test, yhat)print('Accuracy: %.3f' % score)

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

...# plot learning curvespyplot.title('Learning Curves')pyplot.xlabel('Epoch')pyplot.ylabel('Cross Entropy')pyplot.plot(history.history['loss'], label='train')pyplot.plot(history.history['val_loss'], label='val')pyplot.legend()pyplot.show()

Если связать всё это вместе, полный пример оценки нашего первого MLP в наборе данных банкнот приведён ниже.

# fit a simple mlp model on the banknote and review learning curvesfrom pandas import read_csvfrom sklearn.model_selection import train_test_splitfrom sklearn.preprocessing import LabelEncoderfrom sklearn.metrics import accuracy_scorefrom tensorflow.keras import Sequentialfrom tensorflow.keras.layers import Densefrom matplotlib import pyplot# load the datasetpath = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/banknote_authentication.csv'df = read_csv(path, header=None)# split into input and output columnsX, y = df.values[:, :-1], df.values[:, -1]# ensure all data are floating point valuesX = X.astype('float32')# encode strings to integery = LabelEncoder().fit_transform(y)# split into train and test datasetsX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33)# determine the number of input featuresn_features = X.shape[1]# define modelmodel = Sequential()model.add(Dense(10, activation='relu', kernel_initializer='he_normal', input_shape=(n_features,)))model.add(Dense(1, activation='sigmoid'))# compile the modelmodel.compile(optimizer='adam', loss='binary_crossentropy')# fit the modelhistory = model.fit(X_train, y_train, epochs=50, batch_size=32, verbose=0, validation_data=(X_test,y_test))# predict test setyhat = model.predict_classes(X_test)# evaluate predictionsscore = accuracy_score(y_test, yhat)print('Accuracy: %.3f' % score)# plot learning curvespyplot.title('Learning Curves')pyplot.xlabel('Epoch')pyplot.ylabel('Cross Entropy')pyplot.plot(history.history['loss'], label='train')pyplot.plot(history.history['val_loss'], label='val')pyplot.legend()pyplot.show()

Запуск примера сначала соответствует модели в наборе обучающих данных, а затем сообщает о точности классификации в наборе тестовых данных.

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

В этом случае мы видим, что модель достигла идеальной точности в 100 % процентов. Это может означать, что задача прогнозирования проста и/или что нейронные сети хорошо подходят для этой задачи.

Accuracy: 1.000

#

Мы видим, что модель хорошо сходится и не показывает никаких признаков переобучения или неполного соответствия.

С первой попытки у нас всё получилось на удивление хорошо.

Теперь, когда у нас есть некоторое представление о динамике обучения для простой модели MLP в наборе данных, мы можем взглянуть на разработку более надёжной оценки производительности модели в наборе данных.

Оценка робастной модели

K-кратная процедура перекрёстной проверки может обеспечить более надёжную оценку производительности MLP, хотя она может быть очень медленной.

Это связано с тем, что необходимо подобрать и оценить k моделей. Это не проблема, если размер набора данных невелик, например наш набор данных.

Мы можем использовать класс StratifiedKFold и вручную пронумеровать каждую, подогнать модель, оценить её, а затем сообщить среднее значение оценок в конце процедуры.

...# prepare cross validationkfold = KFold(10)# enumerate splitsscores = list()for train_ix, test_ix in kfold.split(X, y):# fit and evaluate the model.........# summarize all scoresprint('Mean Accuracy: %.3f (%.3f)' % (mean(scores), std(scores)))

Мы можем использовать эту структуру для разработки надёжной оценки производительности модели MLP с нашей базовой конфигурацией и даже с рядом различных подготовок данных, архитектур моделей и конфигураций обучения.

Важно, чтобы мы сначала разработали понимание динамики обучения модели на наборе данных в предыдущем разделе, прежде чем использовать перекрёстную проверку в k раз для оценки производительности. Если бы мы начали настраивать модель напрямую, мы могли бы получить хорошие результаты, но если нет, мы могли бы не знать, почему, например, модель недостаточно подогнана.

Если мы снова внесём в модель большие изменения, рекомендуется вернуться назад и убедиться, что модель сходится надлежащим образом.

Полный пример этой структуры для оценки базовой модели MLP из предыдущего раздела приведён ниже.

# k-fold cross-validation of base model for the banknote datasetfrom numpy import meanfrom numpy import stdfrom pandas import read_csvfrom sklearn.model_selection import StratifiedKFoldfrom sklearn.preprocessing import LabelEncoderfrom sklearn.metrics import accuracy_scorefrom tensorflow.keras import Sequentialfrom tensorflow.keras.layers import Densefrom matplotlib import pyplot# load the datasetpath = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/banknote_authentication.csv'df = read_csv(path, header=None)# split into input and output columnsX, y = df.values[:, :-1], df.values[:, -1]# ensure all data are floating point valuesX = X.astype('float32')# encode strings to integery = LabelEncoder().fit_transform(y)# prepare cross validationkfold = StratifiedKFold(10)# enumerate splitsscores = list()for train_ix, test_ix in kfold.split(X, y):# split dataX_train, X_test, y_train, y_test = X[train_ix], X[test_ix], y[train_ix], y[test_ix]# determine the number of input featuresn_features = X.shape[1]# define modelmodel = Sequential()model.add(Dense(10, activation='relu', kernel_initializer='he_normal', input_shape=(n_features,)))model.add(Dense(1, activation='sigmoid'))# compile the modelmodel.compile(optimizer='adam', loss='binary_crossentropy')# fit the modelmodel.fit(X_train, y_train, epochs=50, batch_size=32, verbose=0)# predict test setyhat = model.predict_classes(X_test)# evaluate predictionsscore = accuracy_score(y_test, yhat)print('>%.3f' % score)scores.append(score)# summarize all scoresprint('Mean Accuracy: %.3f (%.3f)' % (mean(scores), std(scores)))

Выполнение примера выводит результат о производительности модели на каждой итерации процедуры оценки и выводит среднее значение и стандартное отклонение точности классификации в конце выполнения.

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

В этом случае мы видим, что модель MLP достигла средней точности около 99,9 %.

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

Это удивительно (для меня), потому что я ожидал, что потребуется некоторое масштабирование данных и, возможно, преобразование мощности.

>1.000>1.000>1.000>1.000>0.993>1.000>1.000>1.000>1.000>1.000Mean Accuracy: 0.999 (0.002)

Затем давайте посмотрим, как мы можем подогнать окончательную модель и использовать её для прогнозов.

Окончательная модель и прогнозы

Как только мы выбираем конфигурацию модели, мы можем обучить окончательную модель на всех доступных данных и использовать её для прогнозирования новых данных.

В этом случае мы будем использовать модель с отсевом и небольшим размером в качестве нашей окончательной модели.

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

...# split into input and output columnsX, y = df.values[:, :-1], df.values[:, -1]# ensure all data are floating point valuesX = X.astype('float32')# encode strings to integerle = LabelEncoder()y = le.fit_transform(y)# determine the number of input featuresn_features = X.shape[1]# define modelmodel = Sequential()model.add(Dense(10, activation='relu', kernel_initializer='he_normal', input_shape=(n_features,)))model.add(Dense(1, activation='sigmoid'))# compile the modelmodel.compile(optimizer='adam', loss='binary_crossentropy')

Затем мы можем использовать эту модель для прогнозирования новых данных.

Во-первых, мы можем определить ряд новых данных.

...# define a row of new datarow = [3.6216,8.6661,-2.8073,-0.44699]

Примечание: я взял эту строку из первой строки набора данных, и ожидаемая метка "0".

Затем мы можем сделать прогноз.

...# make predictionyhat = model.predict_classes([row])

Затем инвертируем преобразование прогноза, чтобы мы могли использовать или интерпретировать результат в правильной метке (которая является просто целым числом для этого набора данных).

...# invert transform to get label for classyhat = le.inverse_transform(yhat)

И в этом случае мы просто выведем прогноз.

...# report predictionprint('Predicted: %s' % (yhat[0]))

Если связать всё это вместе, полный пример подгонки окончательной модели для набора данных банкноты и её использования для прогнозирования новых данных приведён ниже.

# fit a final model and make predictions on new data for the banknote datasetfrom pandas import read_csvfrom sklearn.preprocessing import LabelEncoderfrom sklearn.metrics import accuracy_scorefrom tensorflow.keras import Sequentialfrom tensorflow.keras.layers import Densefrom tensorflow.keras.layers import Dropout# load the datasetpath = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/banknote_authentication.csv'df = read_csv(path, header=None)# split into input and output columnsX, y = df.values[:, :-1], df.values[:, -1]# ensure all data are floating point valuesX = X.astype('float32')# encode strings to integerle = LabelEncoder()y = le.fit_transform(y)# determine the number of input featuresn_features = X.shape[1]# define modelmodel = Sequential()model.add(Dense(10, activation='relu', kernel_initializer='he_normal', input_shape=(n_features,)))model.add(Dense(1, activation='sigmoid'))# compile the modelmodel.compile(optimizer='adam', loss='binary_crossentropy')# fit the modelmodel.fit(X, y, epochs=50, batch_size=32, verbose=0)# define a row of new datarow = [3.6216,8.6661,-2.8073,-0.44699]# make predictionyhat = model.predict_classes([row])# invert transform to get label for classyhat = le.inverse_transform(yhat)# report predictionprint('Predicted: %s' % (yhat[0]))

Выполнение примера соответствует модели для всего набора данных и делает прогноз для одной строки новых данных.

Примечание: ваши результаты могут различаться из-за стохастической природы алгоритма или процедуры оценки или различий в числовой точности. Попробуйте запустить пример несколько раз и сравните средние результаты.

В этом случае мы видим, что модель предсказала метку 0 для входной строки.

Predicted: 0.0

Дальнейшее чтение

В этом разделе представлены дополнительные ресурсы по теме, если вы хотите углубиться в тему.

Вывод

В этом руководстве вы узнали, как разработать модель нейронной сети многослойного персептрона для набора данных двоичной классификации банкнот.

В частности, вы узнали:

  • как загрузить и обобщить набор данных о банкноте и использовать результаты, чтобы предложить подготовку данных и конфигурации модели для использования;

  • как изучить динамику обучения простых моделей MLP в наборе данных;

  • как разработать надёжные оценки производительности модели, настроить производительность модели и сделать прогнозы на основе новых данных.

Узнайте, как прокачаться в других специальностях или освоить их с нуля:

Другие профессии и курсы
Подробнее..

Получится ли сэкономить, отказавшись от Microsoft Office?

16.04.2021 14:07:36 | Автор: admin


Так или иначе, свободное программное обеспечение всегда конкурирует с проприетарным, явно или скрыто. Даже если сами авторы свободных программ не противопоставляют их закрытому софту, конкуренция идет в головах пользователей, которые выбирают платные программы или их бесплатные аналоги. Не один десяток лет с переменным успехом идут горячие баталии между сторонниками открытого и закрытого программного обеспечения: Linux против Windows, Gimp против Photoshop и, конечно же, OpenOffice/Libreoffice против Microsoft Office.

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

Немного истории


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

OpenOffice имеет древнего предшественника StarOffice. Он был выпущен в 1985 году компанией Star Division, основанной немецким подростком Марко Беррисом, когда ему было всего 16 лет. Стив Джобс и Билл Гейтс были гораздо старше, когда они основали свои империи! Естественно, силы были неравны, потому что в 1990 году Microsoft была уже крупной и успешной компанией. Сразу после выпуска Windows 3.0 одна только недельная прибыль составила больше 100 000 долларов. Глобально конкурировать с гигантом Билла Гейтса было нереально, но в 1997 году на своей родине продукт Марко завоевал четверть рынка офисного программного обеспечения за счет меньшей цены (Word и Excel тогда стоили примерно по 50 долларов).

Забавный факт: до того, как офисный пакет Microsoft Word стал доминирующим на рынке, в конце 80-х и начале 90-х самым популярным был WordPerfect, и цена на него была около 150 долларов. Конкуренция положительно сказывается на ценах, пока какая-нибудь компания не добивается монополии.

На волне успеха, в 1998 году, Марк делает офисный пакет бесплатным для личных целей, а через год продает свою компанию Sun Microsystems, которая в свою очередь делает StarOffice бесплатным, но уже и для коммерческого использования. В 2000 году был открыт исходный код офисного пакета, и началась история проекта OpenOffice.org. В 2010 году Sun Microsystems была поглощена Oracle, а немного позднее из-за разногласий в политике управления проект разделился на OpenOffice, который берет под крыло фонд Apache, и LibreOffice, развиваемый The Document Foundation. Различия в этих пакетах не настолько велики, как между ними обоими и Microsoft, поэтому дальше речь пойдет преимущественно про OpenOffice.

Microsoft всегда славилась агрессивной политикой продвижения своих продуктов. Огромное количество денег позволяло сильно демпинговать на рынке программного обеспечения и разорять конкурентов. Кроме того, софтверный гигант никогда не стеснялся грязной игры, их торговые представители щедро раздавали взятки и откаты чиновникам, которые принимали решения о внедрении программных продуктов в частных компаниях и государственных организациях. Ответственные лица закупали программные продукты у Microsoft со скидками до 30%, а государству продавали уже по полной цене, прикарманивая разницу. Ходят слухи, что в МТС в 2012 году не просто так стали рекламировать Windows Phone вместо iPhone. В 2013 году разразился скандал: Microsoft взятками продвигала свое программное обеспечение в России, Пакистане, Китае и странах Восточной Европы. До суда дело снова не дошло, но шум был поднят изрядный. Подавляющее большинство подобных нарушений не получается довести до суда, потому что богатая компания успевает обрубить хвосты и подчистить за собой грязь, но в 2019 году ей пришлось выплатить 25 миллионов долларов за досудебное урегулирование дела о коррупции.

Понятно, что фонды, поддерживающие разработку свободного программного обеспечения, не могут позволить себе подобную политику продвижения, как по этическим соображениям, так и финансово. Потому им невероятно сложно выдерживать конкуренцию с софтверным гигантом. Фактически благодаря стараниям Microsoft пакет Microsoft Office стал стандартом для делопроизводства во всем мире. Судебные иски никак не изменили этот факт, а выплачиваемые штрафы и прочие судебные расходы пренебрежимо малы по сравнению с прибылью компании.

Проблемы совместимости, постепенная эволюция


Исходя из сказанного выше, становится понятно, что, если программный пакет позиционируется как конкурент Microsoft Office, ему, волей-неволей, придется обеспечивать совместимость с документами Microsoft, иначе им никто не будет пользоваться. Но в пакете Microsoft Office используется проприетарные форматы файлов. Вплоть до 2008 года, когда под давлением ISO Microsoft была вынуждена открыть форматы своих файлов на условиях FRAND, сторонние офисные программы были вынуждены обеспечивать совместимость с файлами Microsoft Office с помощью реверс инжиниринга. Естественно, это не могло обеспечить полной совместимости и сильно мешало распространению альтернатив. Более того, в опубликованных спецификациях есть много белых пятен, из-за чего даже сейчас все еще нет полной совместимости между Microsoft Office, Libreoffice и OpenOffice.

Кроме того, форматы файлов Microsoft Office очень долго несли на себе бремя обратной совместимости со старыми версиями, которые были чрезвычайно сложными. Открытая документация только на один формат Excel 97-2003 содержит несколько сотен страниц! Из-за этого казалось, что файлы намеренно запутаны и созданы сумасшедшими программистами. Но это не совсем так. Форматы файлов настолько сложны для того, чтобы можно было обеспечить быструю работу с ними на очень старых и медленных компьютерах, даже при большом объеме данных. Ранние версии Microsoft Office были рассчитаны на работу машин с процессорами Intel 386 и всего 1 Мб оперативной памяти, а большие документы приходилось редактировать уже тогда. Потому документ был чем-то вроде контейнера с внутренней файловой системой, очень похожей на Microsoft-DOS, с таблицей разделов, секторами и файлами, содержащими отдельные части документа. Это было необходимо для обеспечения быстрой работы с данными. Например, в пакете версии 95-97 была команда Fast save, которая позволяя делать инкрементальные сохранения, не перезаписывая весь документ, а добавляя изменения в конец файла.

Еще одна причина сложности формата поддержка составных документов, которая позволяет встраивать в один документ часть из другого документа как объекта OLE, например, таблицу из Excel в документ Word, которая будет обновляться, когда изменится файл таблицы.

В работе над пакетом Microsoft Office, чтобы он имел все современные возможности входящих в него программ, были потрачены тысячи человеко-часов компанией, которая имела достаточно средств, чтобы нанимать высококвалифицированных инженеров. Увы, но команды, разрабатывающие OpenOffice и Libreoffice, намного меньше. При том, что нельзя реализовать только 20% самого популярного функционала и надеяться, что 80% пользователей будут довольны вашей программой. Хороший пример Google Docs, при работе с которым иногда очень не хватает возможностей Microsoft Word, не реализованных в облачном редакторе. Потому перед разработчиками конкурентов Microsoft Office стоит практически непосильная задача, с которой они почти справляются. В течении многих лет постепенно были решены многие проблемы совместимости, но перечислим те, которые еще остались и могут представлять проблемы (в основном, на примере OpenOffice):

  • Очень долгое время была проблема с графиками и диаграммами, созданными в программе Excel. Если файл Excel открывался в Calc, то часть графиков слетала, а если добавить графики программой Calc, то наоборот они слетали при открытии файла в Экселе. Эта проблема не решена полностью до сих пор. Например: круговая диаграмма и диаграмма пирог из Excel (Calc преобразует в 2D-столбцы), невозможность повернуть ось, в частности, чтобы Y внизу была положительной, отсутствие бухгалтерского формата с символом валюты у левого края ячейки.
  • Если в компании практикуется совместное редактирование документов, которые лежат на общем сервере, то перейти на OpenOffice будет сложно или невозможно. Документ, открытый по сети одним пользователем, будет доступен другим только для чтения, а кнопка Редактировать документ, скорее всего, создаст локальную копию.
  • В Calc можно обеспечить совместное редактирование, хоть и с некоторыми ограничениями (нельзя удалять и добавлять строки и столбцы). Для решения этой проблемы во Writer надо создать специальный файл типа Составной документ, который придется экспортировать, чтобы потом его мог открыть пользователь Microsoft Office.
  • Работа со связанными документами в OpenOffice и Microsoft Office реализована по разному, и потому файлы Microsoft Office, открытые в OpenOffice, потеряют все связи. В Microsoft Office можно вставить документ из другого файла с сохранением связи между ними. При открытии такого документа в OpenOffice связь будет потеряна. Например, диаграмма или таблица из Excel, вставленная в текстовый документ, останется, но если отредактировать документ с таблицей, в текстовом файле изменения уже не отобразятся.
  • До сих пор не решена проблема с паролями в документах электронных таблиц. Calc сбрасывает пароль, заданный в файле Excel и наоборот.
  • Ограниченное количество словарей для проверки грамматики и орфографии, навскидку, нет финского языка. Нельзя сказать, что он очень распространенный, но Microsoft Office предоставляет гораздо большее разнообразие в этом вопросе.
  • Не реализован корректный импорт формата RTF. Он все менее популярен и его поддержка прекратилась аж в 2008 году, но если в компании имеются такие документы, работать с ними будет сложно.
  • В пакете OpenOffice до сих пор не работают макросы, написанные на VBA для Microsoft Office.
  • Слабая интеграция с облаками. В OpenOffice вообще нет возможности прозрачно работать с документами в облаке, в Libreoffice есть опция Сохранить в облако, можно настроить несколько сервисов, но обеспечить совместную работу с облачным документом, как это реализовано в Office 365 или Google Docs, эти программные пакеты не позволяют.
  • Корпоративные пользователи будут недовольны тем, что отсутствует интеграция с Outlook.
  • Из небольших и странных несовместимостей: OpenOffice не поддерживает буквицы, а Impress (программа для создания презентаций), не понимает сложные градиенты и анимации PowerPoint, их надо упрощать перед тем, как открыть презентацию OpenOffice. Кроме того, отсутствуют некоторые инструменты чисто отечественной специфики, такие, как автоматическое создание отчетности для налоговой службы и пенсионного фонда. Имеется плохая совместимость с программой 1С. До сих пор есть шероховатости при импорте и экспорте математических формул, а некоторые файлы Microsoft Office слишком долго открываются. Отдельные виды теней и стрелок не поддерживаются в OpenOffice и могут слетать при открытии документа.

Самое любопытное то, что, если создавать текстовые документы по всем правилам, не пытаясь превратить его в чертеж или редактировать в фотошопе заголовки во все цвета радуги, избегать дилетантского форматирования пробелами, пользоваться стилями абзацев и шаблонами, несовместимость документов стремится к нулю. Но такой уровень работы с Офисом (любым) встречается очень редко. Обычно люди используют текстовый процессор на пару процентов от его возможностей, как чуть более продвинутый Блокнот.

Все это создает сложности при миграции с Microsoft Office на открытый и бесплатный софт, несколько примеров ниже это подтверждают.

Самые крупные попытки миграции


В далеком 2003 году власти Мюнхена решили начать проект LiMux. Так назывался дистрибутив на основе Ubuntu с небольшими модификациями для установки на компьютеры муниципальных чиновников. В 2004 году Microsoft прекратила поддержку Windows NT, и надо было решать, как быть: переходить на открытое и бесплатное программное обеспечение или на новую систему от Microsoft и обновлять остальные программы. В 2004 году власти объявили о намерении перейти на открытое программное обеспечение. Фактический он начался в 2005 году и был почти полностью завершен в 2012-2013 годах.

Недолго музыка играла. В 2014 году было сказано, что переход на Linux был катастрофой, и все компьютеры будут обратно переведены на Windows и Microsoft Office. Проблем было несколько.

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

Во-вторых, возникали сложности по конвертации старых документов в новый формат, и особенно сложно было обмениваться документами с другими министерствами и организациями, потому что проблем совместимости тогда было гораздо больше, чем перечислено выше. В департаментах использовалось больше 20 тысяч шаблонов документов Microsoft Office и почти 1000 макросов, которые потребовали серьезных усилий на переделку.

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

Обратный переход обошелся казне почти в 90 миллионов евро и продолжался до 2020 года.
Забавнее всего, что за год сменилась администрация города, были выбраны новые политики, и они снова решили попытаться перевести городскую администрацию на открытый софт. Далеко не всем нравится подобная чехарда, и критики называют это решение политическим, а не рациональным.

Любителям теорий заговора понравится обоснование перехода обратно на Windows. В 2014 году мэром Мюнхена стал Дитер Рейтер, открыто симпатизирующий Microsoft, а в 2016 году исследование эффективности работы муниципальных служб было заказано компании Accenture, которая сотрудничает с Microsoft. Учитывая, что последняя не раз была поймана на взятках, подозрения имеют под собой все основания.

Другая неудачная попытка соскочить с иглы Windows тоже была предпринята в Германии. В 2004 году МИД объявил, что собирается отказаться от продукции Microsoft в пользу открытого ПО. В 2008 году они бодро отрапортовали, что все идет хорошо, экономится много денег, а проблемы совсем незначительные, и через год все закончится. Но в 2011 году Министерство заявило, что отказывается от открытого ПО и возвращается на Windows. Причины были предсказуемы: возникало слишком много проблем в обмене документами с другими ведомствами.

В 2005 году Министерство юстиции Бельгии заявило, что собирается переходить на открытое ПО, а в 2008 половина компьютеров уже работала на SUSE Linux и OpenOffice вместо Microsoft. Основная сложность снова очевидна: проблемы в обмене документами, плюс ко всему не было открытого аналога, который умеет работать с файлами Microsoft Access. Судя по всему, у них это получилось лучше, чем у немцев, потому что другие министерства и администрации городов тоже постепенно переходят на Linux и новостей об громком отказе пока нет, а проблему с Microsoft Access решили переходом на PostgreSQL.

Итоги


Какие выводы можно сделать из всей этой информации? Выгодно ли переходить на открытое ПО и сколько можно сэкономить?

Если говорить о большой компании, где документооборот десятилетиями идет на Microsoft Office, написано множество легаси-кода в макросах, изощренные таблицы с разнообразными диаграммами, а документы разных форматов содержат связи друг на друга, используя OLE, вся отчетность построена на множестве готовых шаблонов, а инфраструктура на Active Directory, переходить на свободное ПО почти невозможно, на грани смерти подобно. Усилия по переучиванию сотрудников, переписыванию шаблонов и макросов, созданию и поддержке новой инфраструктуры несоизмеримы с выгодой отказа от платного ПО.

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

Если работа компании плотно завязана на специфичный софт типа 1С, то им по любому придется оставить несколько машин работающих на Windows с Microsoft Office, чтобы избежать проблем интеграции с этой чудо-системой. Фирмам, чья специфика подразумевает совместную работу с документами, OpenOffice тоже может создать слишком большие сложности, чтобы оправдать переход от платных конкурентов.

Зато молодая и небольшая компания, не создающая изощренных документов, чья работа не связана с интенсивным обменом документами с другими организациями, легко может отказаться от платного ПО и пользоваться одним из открытых Офисов, даже если они останутся на Windows.
Что касается обычных пользователей, то тут проблем вообще нет. Редко кому при обычном домашнем использовании требуются такие возможности, как связанные документы, совместное редактирование и изощренные макросы. А интерфейс, аналогичный старому Офису, с нормальным выпадающим меню, как у всех программ, куда удобнее, чем нелепые панели, которые были введены каким-то врагом дизайна, и предназначены для использования чужаками или хищниками.

***
И что же выбрать, на мой взгляд?

Google Docs!

Шутки шутками, но облачная модель работы с документами существенно привлекательнее, чем традиционная оффлайновая работа. Речь идет не только о Google Docs, но и о Office 365, Dropbox и множестве других сервисов облачной работы с документами. В них из коробки имеется коллективная работа над документами, там просто разграничивать права, делиться ими с другими пользователями или организациями достаточно послать ссылку, не скачивая или пересылая файлы. Сохранность документа не зависит от капризов софта или неполадок железа. Встроенная версионность куда удобнее, чем Undo/Redo, история которых теряется при закрытии локального документа. Работа с документом или его просмотр доступны практически с любого устройства, где есть браузер, от десктопа до смартфона. Эта статья, как и все остальные, написана в Google Docs. И пусть мне иногда не хватает возможностей полноценного Офиса, это компенсируют другие удобства. А в случае чего, подписка на облачные сервисы стоит на порядок дешевле, чем когда-то приходилось тратить на однократную покупку лицензионного софта.
И на этом поле открытое ПО пока проигрывает большим компаниям и платным решениям.



Наши серверы можно использовать для установки любой панели управления.

Зарегистрируйтесь по ссылке выше или кликнув на баннер и получите 10% скидку на первый месяц аренды сервера любой конфигурации!

Подробнее..

Как оформить резюме, чтобы его заметили и увеличить отклик в 3 раза

03.04.2021 10:09:09 | Автор: admin
  • Что учесть при составлении резюме разработчику, чтобы получить хорошие предложения уже в первые 3 дня поисков?

  • Как оценивать стоимость своих навыков и не продешевить?

  • Как описывать опыт и писать сопроводительные письма?

  • Чего никогда не нужно делать в резюме?

Эти и другие вопросы мы с вами обсудим в данной статье.

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

Кстати, если вам больше нравится формат видео, то предлагаю заглянуть ко мне на канал IT DIVA и ознакомиться с видео про составление резюме и прохождение собеседований. А любителям аудио-формата предлагаю воспользоваться расширением-читалкой для Habr'a из моей предыдущей статьи.

Начнём с простого.

Где искать работу?

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

Помимо стандартных HeadHunter, Работа.ру и Зарплата.ру, разработчикам стоит рассматривать варианты, где вакансии выставляются преимущественно для них, например, Хабр.Карьера и LinkedIn. На этих площадках за вами буквально охотятся. Так помогите вас найти ;)

Вообще, всегда используйте несколько каналов для поиска работы, чтобы ускорить его.

Кстати, вы можете добавиться ко мне в сеть LinkedIn, чтобы через общих знакомых выходить на интересные вам компании и предложения.

Как повысить количество откликов на резюме и сопроводительные письма?

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

Резюме, в котором указана "сборная солянка" ваших умений, только запутает рекрутера. Будет непонятно, на чём вы специализируетесь. В итоге вам часто будут приходить неинтересные вам предложения.

Например, я искала вакансию на C#, но из-за того, что у меня в навыках был описан опыт работы с Python и Machine Learning, мне предлагали несколько вакансий в компаниях, которые занимаются преимущественно машинным обучением, что на тот момент не было мне интересно. Я потратила время рекрутеров и своё таким образом. Не совершайте моих ошибок.

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

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

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

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

При описывании своего опыта, не забывайте подкреплять его доказательствами: картинками или gif-анимациями, ссылками на работы и GitHub, статьями и публикациями, а также описанием того, чего вам лично удалось достигнуть благодаря вашим действиям. Помните, что вы пишете о себе, а не о вашей команде.

По ссылкам не должно быть никаких архивов для скачивания или требования регистрации для просмотра. Всё должно быть просматриваемо в два клика.

Если в вашей работе важны Soft-skills, то не забывайте подкреплять примерами не только свои навыки, но и свои положительные качества, например так: "Благодаря моей коммуникабельности мы смогли повысить продажи и за месяц привлечь 20 новых клиентов".

Пример описания опыта с выделением ключевых фраз

Я сократила ежемесячные расходы компании на 30% благодаря внедрению системы автоматической техподдержки. Система была написана мной на языке C# с использованием Razor для .ASP NET. В качестве базы данных была использована СУБД PostgreSQL.

Количество мест работы лучше ограничить до трёх последних, где у нас есть достижения. В образовании, если их несколько, лучше писать то, которое относится к должности. Также можно упомянуть пройденные релевантные курсы.

Указывайте в контактах свою выделенную под рабочие запросы почту и ссылки на свои социальные сети, через которые можно с вами связаться (заранее приведите их в порядок). Так некоторым HR, компаниям и отдельным лицам будет проще связаться с вами, а также получить представление о вашей адекватности и жизненных ценностях. Да, наиболее интересных кандидатов пробивают.

Эти рекомендации отлично работают и для откликов на вакансии в сопроводительном письме. Единственное, что их отличает: на сопроводительное письмо вам может прийти отказ, поэтому не забудьте упомянуть право рекрутера отклонить вашу кандидатуру.

Как написать хорошее сопроводительное письмо?

Немного хочу остановиться на откликах в письмах. Большинство людей просто сбрасывает своё резюме на почту рекрутеру, вот и весь отклик на вакансию. Не надо так!

Напишите лучше сопроводительное письмо к своему резюме.

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

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

Во-вторых, коротко расскажите о себе и своём опыте, как бы отвечая на требования вакансии. Не забывайте подтверждать свой опыт доказательствами, например, в виде ссылок на ваши проекты.

В-третьих, прикрепите резюме с вашим именем и названием вакансии, чтобы отделить вас от других кандидатов и быстро найти.

Вот пример моего отклика на реальную вакансию.

Пример вежливого сопроводительного письма

Здравствуйте!

Откликаюсь на вакансию Unity программиста DreamPort в Екатеринбурге: https://ekaterinburg.hh.ru/vacancy/43313459

Меня зовут Татьяна, мне 23 года, я выпускница направления "Программная инженерия" в УрФУ.

Последние 2 года занимаюсь кроссплатформенной разработкой на Unity под PC, Android и VR (мобильный и стационарный), и знаю особенности оптимизации контента под данные платформы.

Имею опыт разработки клиент-серверных приложений. Умею настраивать UI, работать с системой контроля версий Git и настройкой SteamVR.

На текущем месте работы выполняю роль руководителя проекта:

  • занимаюсь постановкой задач команде и прогнозированием сроков;

  • разрабатываю архитектуру приложения и расширяю его функциональные возможности;

  • провожу код-ревью и контроль качества продукта (тестирование);

  • занимаюсь наставничеством и мотивированием команды.

За последний год работы сократила время выпуска приложений благодаря созданию автоматизированной системы настройки сцен для продукта, а также сократила ежемесячные расходы компании на 12% благодаря введению технологий, заменяющих ранее используемые сторонние сервисы.

До работы в текущей компании реализовала игровой проект на Unity с использованием языка С# в рамках командной работы: https://github.com/EnjiRouz/2D-Fantasy-Game .

В нём я реализовала диалоговую систему, систему поведения вражеских NPC, алгоритмы генерации объектов, а также основную логику поведения персонажа. Дополнительно занималась настройкой анимаций и сцен, а также созданием UI.

К данному письму прикладываю резюме, где вы сможете более детально ознакомиться с моими проектами и опытом: Татьяна Бабичева, резюме для вакансии Unity программист.pdf

Буду рада продолжить общение, если я вам подхожу.

Татьяна Бабичева, /*телефон или телеграм*/

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

Кроме того, я очень рекомендую вам прочесть книгу "Новые правила деловой переписки" Ильяхова М. и Сарычевой Л.. Там есть очень хорошие примеры того, как откликаться на вакансии, да и в целом вести деловое общение.

Как формировать зарплатные ожидания?

Если ты ищешь зарплату на такой же должности, то можешь смело завысить свой текущий ценник на 20-30%. Но тут нужно быть готовым к тому, чтобы аргументировать свою стоимость. В других случаях я предлагаю разобраться поглубже.

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

При выборе локации также обратите внимание на возможности удалённой работы или переезда, если вы планируете выходить не на локальный рынок, а на международный или даже просто на более крупный город.

Имейте в виду, одни и те же навыки в Москве и регионах могут оплачиваться совершенно по-разному из-за разной стоимости жизни и возможностей бизнеса, и это нормально. Так что, если вы хотите получать Московскую зарплату, то вам нужно или переехать или устроиться в качестве удалённого сотрудника.

Сразу отмечу, что людям без опыта работы релокацию оплачивать с высокой вероятностью не будут, так что пожалуйста, не нужно писать рекрутерам сообщения из серии "Возьмите меня, я хочу жить в Питере/Москве". Без шуток, люди так делают О_О

Тем, кто только начинает свой карьерный путь в роли стажёра или Junior, я рекомендую сразу снизить свои зарплатные ожидания до 25-35 тыс. рублей, особенно в регионах. В самом лучшем случае ваша зарплата может достигать 45 тыс. рублей на старте до вычета налогов. Также, новичкам лучше искать первую работу в рамках своего места жительства, если, конечно, у вас нет опыта удалённой работы на стороннего заказчика.

Возможно, кто-то спросит, почему мы часто видим у вакансий такой большой диапазон зарплат, например, от 80 тыс. рублей до 150 тыс. рублей?

Дело в том, что параллельно на одно место может происходить поиск двух разных по уровню специалистов: например, для программистов, это может быть одновременный поиск middle или senior на одну или более позиций в компании.

Кстати, этот диапазон поможет нам определить уровень зарплаты, до которого мы можем дойти в компании, если у нас на данный момент уровень соответствует нижней границе зарплаты. То есть, сколько мы будем зарабатывать, если продолжим развиваться в компании и будем проявлять себя.

Кстати, о том, как получать повышение, я говорила в недавнем видео на своём YouTube-канале. Кому интересно - заглядывайте.

Чего не нужно делать в резюме?

  • писать чужое имя или использовать чужое фото (да, такое бывает);

  • использовать вульгарное, плохоосвещённое или слишком личное фото (например, с поездки на шашлыки или с ребёнком на руках);

  • писать личную информацию, не относящуюся к работе (фразы типо "мать троих детей" или "в свободное время хожу по ночным клубам", информация о семейном положении и т.д.);

  • рассказывать тупые шутки и невероятные истории из жизни (не отнимайте время у рекрутера);

  • манипулировать рекрутерами (в письме такие фразы "Если ты уделишь всего 2 минуты этому резюме, то убедишься, что лучше кандидата быть не может" только раздражают).

Как зацепить внимание работодателя?

Напоследок, небольшая хитрость: выставляйте работы из портфолио в стиле предпочтительных компаний.

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

Заключение

На этом всё. Надеюсь, теперь вы сможете быстрее найти работу мечты.

Кстати, тех, кто планирует строить карьеру в IT, ябуду рада видеть на своём YouTube-канале IT DIVA. Там вы сможете найти ещё больше полезных материалов по тому как проходить собеседования, получать повышение, справляться с профессиональным выгоранием, управлять разработкой и продумывать архитектуру ПО.

Подробнее..

Я в Японии. Что делать?

02.04.2021 12:23:26 | Автор: admin

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

Виза

Если вы уже нашли работу или учебное учреждение в Японии, работодатель / языковая школа / ВУЗ пришлёт вам DHL или другой курьерской службой доставки Certificate of Eligibility (или Сертификат, определяющий статус заявителя в Японии). Этот документ гарантирует, что работодатель / школа / ВУЗ несет за ответственность за ваше стабильное финансовое положение в Японии и будет оказывать необходимую поддержку. Вместе с этим документом и остальными (полный список здесь) вы отправляетесь в Посольство для подачи заявления на визы. (Лучше предварительно проверьте часы работы Посольства в период карантина и порядок подачи заявлений. Документы также принимают по почте, также только оригиналы). Рабочую или учебную визу выдают быстро (мне дали через 3 дня после подачи заявления), но процесс также может быть немного затянут в связи с последствиями пандемии. Если у вас пока нет приглашения от работодателя, и вы для начала хотите оглядеться, вы можете получить только туристическую визу (список документов для подачи заявления на туристическую визу). По ней вы не сможете работать и учиться, но после получения приглашения от будущего места работы или учебного заведения можно будет подать на визу соответствующего типа. Самая долгая туристическая виза действует 3 месяца, специально под нее языковые школы предлагают учебные программы. За этот срок можно более или менее понять, захотите ли вы тут учиться, жить и работать.

ID-карта ( или дзайрю:ка:до)

Это аналог паспорта, выдается тем иностранцам, кто планирует провести в Японии срок более трёх месяцев. ID необходима для оформления банковской карты, аренды жилья, оформления страховки и т.д. Получить ID можно в отделе миграционной службы, при этом за студентов документы подает учебное заведение (языковая школа, ВУЗ или другое), за сотрудников компания или сам сотрудник (в зависимости от политики работодателя).

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

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

Прочие документы

Прописка, страховка, свидетельство о рождении ребенка оформляются в или куаякусио: (администрации) по месту проживания. Лучше всего сюда приходить с провожатым, говорящим и читающим на японском языке, т.к. обычно японцы либо не говорят по-английски, либо стесняются в этом признаться. Для получения прописки необходим договор аренды квартиры и ID. Страховка оформляется при наличии ID.

Страховка платная. Мне, как студенту университета, пришлось оплачивать страховку в администрации, в общежитии и в самом ВУЗе. Общая сумма примерно 470$. Страховка покрывает лечение и медицинские осмотры (кроме частных клиник, подробнее о медицине напишу ниже), аварийные ситуации, когда вы причинили ущерб другому человеку или чужому имуществу, и наоборот. При аварии нужно получить справку от полиции для подачи в страховую компанию.

Японский язык

На одной из лекций я услышала самое запоминающееся и самое четкое определение для японского языка он является частью высоко-контекстуальной культуры Японии. Контекст здесь это информация, которая нужна для правильной расшифровки сообщений, эта информация так же соотносится с определенными культурными ситуациями. И здесь начинается дремучий прекрасный лес диалектов японского языка и речевого этикета, присущего разным регионам. Можно выучить стандартный японский язык, вас везде поймут, но если в Токио он будет звучать вполне приемлемо, то, например, в Осаке слишком сухо и официально. Здесь много интересных статей про язык и культуру общения.

Это удивительно, но в Японии можно прожить без знания местного языка. Конечно, если вы хотя бы на бытовом уровне можете объясниться с жителями Японии вам будет комфортнее: спросить дорогу, попросить о помощи, уточнить информацию в банке и т.д. Я знаю несколько человек, кто живет и работает в Токио больше трех лет, используя в основном английский язык для работы и общения с друзьями, и базовый японский в быту. Они работают в иностранной компании, в свободное время общаются с англоговорящими иностранцами или японцами и совсем не чувствуют необходимости учить японский язык. Названия улиц, станций и прочие информационные таблички дублируются на английском языке. Возможно, вы не заблудитесь, но, если вы не знаете языка запаситесь карманным wi-fi и внешним аккумулятором для телефона. Если всё же вы ищете школу японского языка, могу порекомендовать Yu Language Academy.

Работа

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

Сложно однозначно оценить отношение к иностранцам в японских компаниях. Где иностранных сотрудников много к ним привычны, где мало иностранцы выделяются. В японском обществе вы в любом случае будете себя чувствовать чужим, в большей или меньшей степени. Это лично мое мнение, но я чувствую, что русские скорее индивидуалисты, и каждый действует, отталкиваясь от своей морали и привычек. А японцы живут и мыслят как группа где бы они ни находились, каждый человек чувствует себя частью определенной группы. Он ничего от нее не скрывает и действует ей во благо. Кстати, японцы любят себя называть хатараки бачи (пчела-работяга), работающие на благо улья.

Это небольшое отклонение от темы здесь лишь затем, чтобы предупредить вас выбирайте компании, где работают иностранцы, там вы наверняка найдёте хороших знакомых или друзей.

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

Деньги

Если вы устраиваетесь на работу или поступаете в учебное заведение, находясь в России, с оформлением документов вам помогут коллеги или представители школы / университета. Нас, студентов, просто брали за руки и водили по всем инстанциям, и нам даже не нужно было общаться с их сотрудниками. Также было и с банком мы пришли туда группой, по очереди подходили на оформление карт и получали их через 2-3 дня. Для оформления банковской карты нужен ID и прописка. У иностранцев могут быть ограничения по онлайн-банкингу, это уже зависит от банка.

Если у вас есть карта, наличные деньги вам не особенно будут нужны. Если же вам комфортнее использовать наличку, в магазинах вы не столкнётесь с трудностями при расчете на кассе у кассиров всегда есть размен. Но если вы будете пользоваться автобусом, не обзаведясь предварительно проездной картой типа Suika, приготовьте мелкие монеты для оплаты проезда. В автобусах установлены терминалы, которые не выдают сдачи, а сами водители не принимают оплату.

Аренда жилья

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

По этой причине в съемных квартирах и комнатах ничего нельзя клеить на стены, и вообще нельзя как-либо портить их, пол или имущество за это могут потребовать компенсацию, когда вы будете съезжать. Моей знакомой пришлось заплатить $600 за небольшое количество пролитого средства для снятия лака на линолеум. Скорее всего, вы не найдёте объявления о сдаче жилья, в которых будет написано с детьми нельзя. Но в отношении домашних животных есть некоторые особенности: квартирантам с собаками легче найти варианты жилья, чем любителям кошек. Возможно потому, что кошки точат когти об мебель. Возможно потому, что многие японцы заводят себе именно миниатюрных собачек и просто более лояльно относятся к собакам. В Токио нет системы центрального отопления, поэтому обогреваются зимой квартиры обогревателями. Я знаю японцев, которые экономят на электричестве зимой и просто не снимают верхнюю одежду дома. Мы часто проводили время в библиотеке. Японские дома довольно холодные и по нашим меркам хлипкие. Как объясняют сами жители островов, дома строят с учётом того, чтобы в случае землетрясения или сильного цунами их не восстанавливать, а стоить новые.

Средние расходы на коммунальные услуги в месяц составляют примерно $180. Из них на электричество приходится $100, на воду $40 и на газ $40. Японцы могут вызвать полицию, если у вас в квартире будет шумно или даже просто людно. При этом если вы объясните полицейским, что вы не шумите, или они сами это поймут, вас просто предупредят. Если же вы действительно шумите полицейские составят рапорт и направят его потом на ваше место работы. Выселять же из квартиры вас будут только за что-то серьёзное, для этого нужно постараться.

Связь

Еще несколько лет назад процедура приобретения сим-карты для иностранца была очень сложной ее можно было купить только вместе с телефоном, заполнив кучу документов. Сейчас всё намного проще, для покупки сим-карты и телефона нужен ID и банковская карта. Среди тарифных планов нет безлимитных. Если вы не планируете надолго оставаться в Японии лучше купите карманный wi-fi роутер (пример на Amazon). Портативный роутер позволяет организовать доступ к интернету с нескольких устройств сразу, независимо от того, какой тариф какого оператора на них используется. Все устройства, подключенные к такому роутеру, пользуются интернетом в рамках установленного на нём тарифного пакета. То есть если на роутере оплачен безлимитный пакет, он будет безлимитным для всех устройств, подключенных к нему. К портативному роутеру можно подключить не только смартфон или планшет, но и любое устройство, оснащённое wi-fi модулем.

Но если вам очень важна высокая скорость интернета, то можно подключить домашний интернет (стоимость очень разнится, от $50 до $100). Найти и выбрать провайдера будет не сложно как только вы поселитесь в квартиру, ваш почтовый ящик будет забит рекламными листовками. У вас будет время спокойно просмотреть их и сравнить. Здесь вы можете прочитать про мобильную связь и ознакомиться с предложениями разных провайдеров. При оформлении сим-карты заключается договор на обслуживание, который обязательно нужно расторгнуть перед отъездом из Японии. Меня очень впечатлили истории о студентах, которые уехали домой с открытым договором и получали через некоторое время внушительные счета за связь.

Общественный транспорт

В Японии очень удобная система общественного транспорта. Расскажу на примере Токио: прежде всего нужно приобрести карту Suika, можно сразу в аэропорту или на любой станции метро. Стоимость карт варьируется от $10 до $100, при этом $5 от стоимости карты не могут быть использованы для оплаты проезда (они составляют залоговую стоимость и могут быть вам возвращены, если вы сдадите карту по окончании периода пребывания в Японии). Остаток является депозитом для оплаты проездов, баланс карты можно пополнить в терминалах на станциях метро. Удобство Suika еще и в том, что ею можно расплачиваться в некоторых магазинах (7-Eleven, Wallmart, etc.), кафе и столовых. Здесь более детальная информация про Suika, в том числе видеоинструкция покупки и использования: https://www.jreast.co.jp/e/pass/suica.html.
Этой картой можно пользоваться и в других регионах, помимо Токио:

Транспорт в Японии двигается в безупречном соответствии с расписанием, из-за этого кажется, например, что автобусы передвигаются чересчур вальяжно. Лучше заранее планировать свой маршрут, я использовала Google maps и выбирала кратчайший и простейший путь, внося станцию отправления и прибытия в поиск.

В автобусах оплата на выходе водителю (которые выглядят вышедшими из сказки, в красивой синей форме и белых перчатках), картой Suika или наличными. Наличные опускаются в автомат, который сдачи не выдает, поэтому если картой вы не обзавелись разменяйте монетки. Стоимость проезда на автобусе зависит от расстояния и района города, например, в центре города $1.99 (городской автобус), $2.08 (частный). Есть автобусы по $0.95 (на окраине города).

Система железных дорог в Токио сведет вас с ума в первого взгляда, но если её не бояться и регулярно пользоваться поездами, разберетесь очень скоро. В Токио есть Tokyo Metro и Toei Subways, у них разные пути, которые очень удобно комбинировать.

Кстати, закладывайте в расчеты время на ориентирование на местности. Однажды я заблудилась в городе-станции Токио, у которой есть несколько выходов на разных этажах, целые улочки с рынками, магазинами и ресторанчиками. Я спрашивала дорогу у прохожих и у сотрудников станции, но никто не смог помочь мне сориентироваться (хотя вопросы были сформулированы на японском). Тут пошла в ход стратегическая хитрость я обозначила для себя ориентир, и всегда приходила к нему как к стартовой точке, от которой можно легко найти нужное направление: Gin-no-Suzu Square (Silver Bell Square или Площадь Серебряного Колокола).

На станциях ориентироваться легко везде есть указатели, но здесь будьте внимательны, т.к. встречаются очень похожие названия линий и станций. Можно также спросить сотрудников станции, они говорят на ломаном английском и языке жестов. Стоимость билетов Tokyo Metro и Toei Subway не зависит от категории поезда есть Regular train и Rapid Train, вам просто нужно выбрать тот, который быстрее доедет до нужной вам станции,и не пропустить её ).

Возможно, вы об этом знаете, но на всякий случай напомню: в Японии нельзя разговаривать в общественном транспорте по телефону и слушать громкую музыку в наушниках. И вообще всячески шуметь. Также не принято уступать место напоказ пожилым людям и беременным женщинам. До того, как я это поняла, я немного испугала одну японку. Она села на моё место, но чувствовала себя некомфортно.

Личный транспорт

Аренда квартиры с парковочным местом стоит дорого, поэтому в основном местные жители и экспаты используют общественный транспорт или велосипед. Мы с одногруппниками сразу купили себе велосипеды. Стоимость велосипеда зависит в первую очередь от модели. Очень распространены велосипеды типа мамачаиро (mother and child) простые взрослики с корзинкой на руле и багажником, к которому можно докупить безопасное детское кресло. Они стоят ориентировочно $100. Дороги в Токио очень комфортные, нет резких подъемов или разбитого асфальта, поэтому передвижение на велосипеде это не только польза для здоровья, но и большое удовольствие. При приобретении велосипеда он регистрируется в магазине на ваше имя, и если вашим транспортом воспользуется кто-либо другой, он может быть задержан полицией для выяснения обстоятельств.

Правила дорожного движения в Японии отдают приоритет пешеходу и велосипедисту перед машиной, поэтому вы всегда будете правы в случае любых недоразумений на дороге. Мне знаком случай, когда велосипедист врезался в стоящую на парковке машину, заработав лишь пару синяков, а владелец готов был оплатить ему лечение в частной клинике только чтобы велосипедист не начинал с ним судиться. Если вы всё же рассматриваете вариант покупки машины, стоит учесть, что аренда квартиры с парковочным местом стоит на порядок дороже. Да и в целом в Токио очень проблемно найти свободную парковку, а пробки не дадут свободно передвигаться по городу. Здесь вас спасет car sharing, он очень распространен в Токио. Японцы, у которых нет своего автомобиля, берут его в аренду для путешествий на один-два дня (ориентировочно $70 в день).

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

Покупки

Сейчас очень популярны сервиса заказа еды и продуктов. Интернет-магазин на все случаи жизни это Amazon. Там вы можете приобрести и продукты, одежду, всё необходимое для дома, занятий спортом и многое другое. Можете заранее посмотреть там стоимость продуктов и других товаров, и составить примерный бюджет на месяц.

Если вы любите погулять по магазинам, потрогать и выбрать товары офлайн найдите ближайшие магазины на карте или двигайтесь в сторону ближайшей станции метро. Рядом с любой станцией метро вы сможете найти торговый центр с супермаркетом, кафе и барами.

Приведу примеры стоимости некоторых продуктов:

  • Молоко 1 литр (3,5%) $2.40 Выбирайте молоко из Хоккайдо на упаковке вы увидите надпись или силуэт острова. Кстати, будьте готовы к тому, что жирность и сам вкус молочных продуктов будет другой будто немного разбавленный.

  • Яйца (10 шт) $2.40

  • Хлеб $1.20-$2.40 Сложно найти не сладкий хлеб, но вам этот квест может понравиться. Ищите пекарни по манящему запаху, в магазинах обычно продается хлеб для сэндвичей и булочки.

  • Сыр 126 гр. в пластиках, 7 шт. $1,70. Первое время после прибытия в Токио я готовила еду сама, но очень скоро заметила, что питаться в кафе или покупать готовую еду дешевле. Кстати, многие супермаркеты делают большие скидки на готовую продукцию в последний час работы.

Медицина

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

Будьте готовы к тому, что в аптеках drug stores, которые встречаются довольно часто в магазинах с бытовой химией и косметикой вам не продадут лекарства без рецепта и не дадут совета при выборе медикаментов. В аптеках работают продавцы, а не фармацевты, и они либо продадут вам тот товар, который вы назовете, либо попросят рецепт врача.

Подработка или арубайто ( )

Этот пункт, возможно, будет интересен студентам языковых школ и университетов. Разрешение на работу можно получить, если ваша виза и срок обучения длится более полугода. У меня была стипендия, и я могла бы получить разрешение только при отказе от неё. Для подработки вам нужно уметь говорить на уровне повседневного общения, читать и немного писать по-японски. Если вы не уверены в своих знаниях можно найти подработку среди русскоязычных пользователей фейсбука в группах типа Помогаем нашим. Там также публикуются вакансии для специалистов со знанием японского и другая интересная информация, так что присоединиться к сообществу будет полезно. Кроме фейсбука существует множество сайтов для поиска работы, на них отдельно останавливаться не буду.

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

Дети

Ребенок, родившийся на территории Японии, получается Свидетельство о рождении, которое выдается на основании proof of birth ( сюссёсиомейсё) своеобразной справки из больницы. При этом ребенок считается гражданином того же государства, что и родители. Во время регистрации ребенка в администрации родители получают медицинскую книжку на ребенка, в которой будет вся информация о приемах врача во время беременности, пройденные учебные классы для беременных, протекании родов, состоянии здоровья матери и ребенка, и многое другое.

Кстати, во время беременности женщина получает уход и необходимое лечение при необходимости в клинике за счет страховки, но палата оплачивается отдельно. Для оформления ребенка в детский сад или школу необходимо сначала подать заявку в администрацию. Сады и школы платные, стоимость рассчитывается исходя из дохода семьи. Выбрать детский сад можно ближайший к дому. Школы есть при консульствах, но заявки туда в них нужно подавать заранее. В основном язык преподавания японский, но можно найти и школы, где дети учатся на английском языке.

Стереотипы

Да, японцы находятся на работе допоздна, и вы зачастую можете увидеть человека в костюме спящим на ступеньках перед входом в станцию. Но не все японцы при этом трудоголики. Просто принято уходить с работы после того, как уйдет домой руководитель. Ты можешь при этом заниматься чем угодно, придавая своему лицу серьезный и деловой вид главное уйти позже, показав этим, насколько для тебя работа важнее личной жизни.Да, они не против выпить. Но многие японцы пьянеют от одного стакана пива и становятся похожими на глупо хихикающих детей. Очень мило, но не очень весело.Кстати, в Японии курят в барах и ресторанах. Есть также заведения, которые запрещают курение в помещении. В общественных местах есть специально отведенные зоны, вне которых курить нельзя, но курить просто на улице не возбраняется.Возможно, извращенцев много. Об этом предупреждают все: если в час-пик в вагоне метро ты чувствуешь, что кто-то начинает к тебе непотребно прикасаться или фотографировать твои ноги и т.д. нужно указать этого человека и громко сказать хэнтай или чикан (извращенец), и люди сами вытолкают его из вагона и сдадут служащему станции. Я ни разу не встречала подозрительных типов, но очень часто слышала предостережения и это уже заставляет задуматься. Кстати, некоторые поезда начинаются с розовых вагонов, куда нельзя входить мужчинам они точно безопасны.

Да, японцев можно назвать стеснительными. Это связано по большей части с культурными особенностями нельзя быть индивидуалистом, нельзя блистать своими знаниями и талантами, нельзя говорить, что тебе что-то удаётся. И в случае с английским языком японец может сказать, что он на нём говорит очень плохо, даже если находится на уровне Advanced.

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

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

Этот пункт возвращает меня к предисловию статьи почему я не хотела бы жить в Японии. В этих глубинах культуры и объемности смыслов очень часто чувствуешь одиночество. Иностранец не является частью контекста Японии. Кроме того, Япония это страна для интровертов, и большую часть японцев можно назвать интровертами. Они держатся на дистанции, и границы её настолько холодны и непонятны, что и ты сам постепенно возводишь вокруг себя защитную стену. Вам поможет любимое дело (а в Японии только ленивый не найдёт себя) и другие иностранцы, с ними вы будете чувствовать себя на одной стороне.

Пока я писала этот текст, я очень старалась избегать категоричных суждений. Их очень легко выносить, но также легко можно и ошибиться. Возможно, вам японский менталитет будет близок, и вы очень комфортно будете себя ощущать в Японии. Это настолько тонко, что можно почувствовать только самостоятельно. Не бойтесь, но будьте готовы!


Автор: Наталья Героева (Veeam), Project Manager.

Подробнее..

В закладки Кунг-фу на клавиатуре. Искусство сочетать клавиши

11.04.2021 14:15:43 | Автор: admin

Сочетания клавиш для тех, кто хочет войти в IT и не только.

Содержание

Сочетания клавиш - это простые команды, позволяющие удерживать пальцы на клавиатуре, а не прыгать вперед и назад к мыши. Вы, вероятно, уже знаете такие распространенные сочетания клавиш, как CTRL + C для копирования и CTRL + V для вставки, но есть множество других сочетаний клавиш, которые позволяют делать что угодно на вашем компьютере или в конкретной программе. Говорят, что знание только основных сочетаний экономит вам 8 рабочих дней каждый год. Цель этой статьи - сэкономить вам ГОРАЗДО больше.

К сожалению, для многих знание "контрол-цэ" и "контрол-вэ" становится верхней границей в использовании комбинаций. Именно для них были написаны первые главы этой статьи, где мы разберем основные сочетания клавиш и советы по эффективному использованию клавиатуры, которые прогонят из вас компьютерную мышь.

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

В конце вы увидите, как все эти знания можно использовать при работе с самым популярным на данный момент текстовым редактором Visual Studio Code.

Не пытайтесь просто запомнить все, что написано в статье. Обязательно попробуйте понажимать все сочетания клавиш, о которых вы не знали! А потом возвращайтесь время от времени, чтобы освежить память.

Если вы пользователь системы Windows, то вы обязаны дочитать до конца.

Поехали.

Базовые сочетания

Базовыми сочетаниями я буду называть те, которые выполняют похожие функции в разных операционных системах и приложениях.

Esc- aka Escape или Эскейп или Эскейт или... ладно, ладно. Тут все просто, она в основном используется для выхода из чего-либо или отмены чего-либо. Если все пошло наперекосяк и "Я что-то нажала и все уронилось", то скорее всего вам нужно будет обратиться к этой клавише.

Tab. Таб это не только символ табуляции, но еще и полезнейший инструмент смены фокуса. Фокус здесь означает то место, на которое будут направлены действия пользователя в системе. Так, например, если у нас в приложении стоит фокус на текстовом поле, то все, что мы печатаем, будет вноситься именно в это поле. Если фокус на кнопке - тоSpaceили в худшем случаеEnterнажмут на эту кнопку. Так что совет тут такой. Когда заполняем формы, переключаемся между полями черезTab, отмечаем галочки черезSpace, решили вернуться -Shift+Tab.

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

Ctrl- работает похожим образом, но позволяет точечно выбирать, что именно вам нужно.

Shift+/<key/>- так исторически сложилось, что Shift часто используется для инвертирования действия, выполненного сочетанием клавиш без Shift. Например Shift+Tab совершает действие, противоположное Tab. Keep in mind!

F1- вызов справки. Просто для справки.

Ctrl+W- закрыть окно, вкладку. Почти всегда работает в приложениях, где есть вкладки.

Ctrl+F- поиск. F - Find.

Ctrl+P. В большинстве программ вызывает меню печати.

Ctrl+S- сохранить. Что тут еще говорить.

Ctrl+Z- отменить действие.

Ctrl+Y/Ctrl+Shift+Z- повторить отмененное действие.

Ctrl+N. Открыть новое окно/файл.

Ctrl+(+)- приблизить/увеличить масштаб.

Ctrl+(-)- отдалить/уменьшить масштаб.

Ctrl+(?shift)+[|Ctrl+(?shift)+]- уменьшить | увеличить размер шрифта.

Shift+Enter- перевести курсор на начало новой строки. Это сочетание бывает необходимо, если нажатиеEnterделает что-то другое.

Графика

Во многих приложениях, где можно работать с графическими элементами, скорее всего заработают следующие сочетания:

Ctrl+D- создать копию объекта. От слова Duplicate.

Ctrl+(?shift)+[- Переместить элемент на задний план. В некоторых программах требуется клавиша модификатор Shift.

Ctrl+(?shift)+]- Переместить элемент на передний план.

Хотя использование мыши - дело, недостойное настоящего погромиста, но иногда без нее никуда.

Эти сочетания мыши критичны для тех, кто работает с графическими элементами.

Ctrl+MouseScroll- увеличить / уменьшить масштаб.

Shift+MouseScroll- переместиться по горизонтали. Иногда весь контент не помещается в окне, и появляется горизонтальная полоса прокрутки. Данное сочетание позволяет перемещаться вправо или влево в таких ситуациях.

Shift+Click- выбрать группу элементов, если возможно.

Ctrl+Click- выбрать элементы, точечно.

Ctrl+(Dragging)- копировать элемент или группу элементов и переместить на позицию курсора. Работает не везде, но полезно помнить.

Терминал Linux

Навигация в терминале не очень удобная. Для того, чтобы немного облегчить жизнь, при работе с этим инструментом, можно воспользоваться скриптом, о котором будет рассказано в разделеAutoHotkey.

Tab- автодополнение команд.

Tab+Tab- вывести список возможных команд автодополнения.

Ctrl+C- послать сигнал прерывания процесса.

Ctrl+Z- приостановить процесс и перевести в фон.

Ctrl+D- удалить символ после курсора. Если строка пустая, то эта команда завершит работу терминала.

Alt+D- удалить слово после курсора.

Ctrl+W- вырезать слово перед курсором.

Alt+Backspace- удалить слово перед курсором.

Ctrl+A- перейти в начало строки.

Ctrl+E- перейти в конец строки.

Ctrl+B- переместиться на символ назад.

Ctrl+F- переместиться на символ вперед.

Windows

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

Парочка полезностей:

  • Поиск через "Start" в Windows работает так, что он быстро находит файлы, находящиеся в системных папках. Поэтому, если вам лень ходить по файловой системе, нажимаемWinи вводим имя файла - система быстро нам его найдет.

  • Если открыть контекстное меню файла с зажатымShift, то появятся дополнительные опции. Одной из них будет "Скопировать как путь", очень удобно.

Сочетания

Win+D- скрыть все окна.

Win+M- свернуть все окна.

Win+Shift+M- развернуть все окна.

Win+X- открыть меню системных инструментов.

Win+P- открыть меню проекции на дополнительные дисплеи.

Win+Left/Right- переместить окно влево/вправо.

Win+Up- развернуть окно на весь экран.

Win+Down- открепить окно / свернуть.

Win+L- заблокировать систему.

Win+B- фокус на панель инструментов.

Win+Ctrl+Left/Right- переключиться между рабочими столами.

Win+(.)- открыть меню стикеров.

Alt+Tab- вы и так знаете. Переключаемся между активными окнами. Зажатый Shift двигает нас назад.

Alt+Enter- позволяет открыть некоторые окна в полноэкранном режиме.

Win+{1, 2, 3, ...}- открыть n-ное окно прикрепленное к панели задач. Обязательно к использованию!

Win+Shift+{1, 2, 3, ...}- открыть n-ное окно от имени администратора.

Win+Shift+S- сделать скриншот части экрана.

Ctrl+Shift+Esc- открыть диспетчер задач.

Alt+\<key\>- активирует навигацию в окнах многих программ. Например, сочетаниеAlt+V + H + Hпозволяет скрыть/показать скрытые файлы в проводнике.

PrintScreenилиPrtScn- сделать снимок экрана. Вроде бы вещь банальная, но, как показывает практика, все еще есть люди, которые фотографируют экран. Скриншот сохраняется в буфер обмена, поэтому, чтобы просмотреть картинку, вам нужно будет ее вставить в соответствующую программу, например Paint.

Alt+PrintScreen- сделать скриншот окна.

Win+PrintScreen- сделать скриншот экрана и сохранить в папку "Изображения".

Проводник

F2- переименовать файл/папку.

Win+E- открыть проводник.

Alt+Enter- открыть свойства файла.

Ctrl+Enter- открыть папку в новом окне.

Ctrl+Shift+N- создать новую папку в текущей директории в проводнике.

Alt+Left/Alt+Right- предыдущая папка / следующая папка в истории.

Alt+Up. Переместиться на уровень вверх.

Утилиты

Magnifier

Win+(+)- увеличить часть экрана.

Win+(-)- уменьшить часть экрана.

Win+Esc- закрыть Magnifier.

Xbox Game Bar

Win+G- открыть игровое меню XBox.

Win+Alt+R- Начать/остановить запись текущего окна. R - Record.

Chrome

В хроме исправно работают многие из сочетаний, описанных вБазовые сочетания.

Ctrl+Shift+W- брат Ctrl+W. Позволяет закрыть все вкладки сразу.

Ctrl+Shift+N- открыть новое окно в режиме инкогнито. Если вам часто нужно открыть "чистое" окно браузера, то запомните это сочетание.

Ctrl+T- открыть новую вкладку и перейти к ней.

Ctrl+Shift+T- открыть ранее закрытую вкладку. В некоторых случаях это поможет восстановить историю вкладок, если браузер был принудительно закрыт.

Ctrl+Tab- перейти к следующей вкладке на панели.

Ctrl+Shift+Tab- перейти к следующей вкладке на панели.

Ctrl+{1, 2, ..., 8}- перейти к n-ной вкладке.

Ctrl+9- перейти к последней вкладке.

Ctrl+R- перезагрузить страницу.

Ctrl+Shift+R- перезагрузить страницу, без использования данных в кэше.

Ctrl+D- сохранить текущую страницу в закладках.

Ctrl+Shift+D- сохранить все открытые вкладки в закладках. Поосторожнее с этим!

Ctrl+L- фокус на адресную строку.

Сочетания мыши

MiddleMouseButton- открыть страницу по ссылке в новой вкладке.

Ctrl+Click- открыть страницу по ссылке в новой вкладке.

Ctrl+Shift+Click- открыть ссылку в новой вкладке и перейти к ней. Обычно это именно то, что нужно, если вы хотите быстро просмотреть информацию по другой ссылке.

Shift+Click- открыть ссылку в новом окне.

Меню

Ctrl+H- открыть историю браузера.

Ctrl+J- открыть страницу загрузок.

Shift+Esc- открыть диспетчер задач Chrome. Если вы не понимаете, какая страница сильно нагружает ваши ресурсы, то стоит сюда заглянуть.

Ctrl+Shift+O- открыть страницу закладок.

Developer tools

Developer tools - один из самых полезных инструментов в арсенале Web-разработчика. Посмотрим, как можно немного ускорить работу с ним в браузере Chrome.

Ctrl+Shift+J- открыть вкладку Console в инструментах разработчика

Ctrl+(backtick)- фокус на консоли. При открытом меню инструментов разработчика.

Ctrl+[,Ctrl+]- сменить вкладку на панели.

F2- редактировать элемент как html.

Ctrl+Shift+P- открыть панель команд. Сочетание, которое может заменить их все.

Ctrl+Shift+I/F12- открыть последнюю использованную вкладку в инструментах разработчика.

Ctrl+Shift+C- открыть панель элементов страницы.

Этого немного, но достаточно, чтобы пользоваться и не перегружать мозг. Больше сочетанийздесь.

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

Vimium

Чего мы хотим?Чего мы хотим?

Vimium- расширение для браузера, которое предоставляет сочетания клавиш для навигации и управления в духе редактора Vim.

Для работы с русской раскладкойнужно будет добавить "мэпы" в настройки вимиума.

Вот что это нам дает.

Переход по ссылкам черезF+<key>.Больше не нужно тянуться за мышкой, чтобы кликнуть по ссылке. Это сделает за вас Vimium. Нажмите клавишуFи на странице к каждой ссылке прикрепится название клавиши, которую нужно нажать далее, чтобы перейти по ней.

Перемещение через сочетания как в виме

Используйте привычные клавишиhjklдля движения по странице.

Панель поиска

  • Ищем везде черезo

  • Ищем в закладках черезb

  • Ищем в открытых вкладках черезT

Я не буду раскрывать все сочетания, для этого есть вот такая хорошая памятка:

Vimium hotkeysVimium hotkeys

AutoHotkey

Вначале будет многа букофф...

Хакерский редактор

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

Vim (сокр. от Vi Improved, произносится вим) кошмар для случайного пользователя. Если его удаётся в конце концов закрыть, то вздыхаешь с облегчением и твёрдой уверенностью, что больше не будешь запускать эту программу ни разу в жизни. (c) Материал из Викиучебника

Так что же в нем особенного? На Хекслете есть неплохаястатья, в которой рассказано, почему Vim - это хорошо.

Я тоже считаю, что вим - это хорошо и знать основные его команды очень пригодится. Так, например, упоминание этого редактора при разговоре с разработчиками даст вам +1 к крутости. А на многих сайтах (например YouTube) используются сочетания именно из этого редактора. Однако реальность такова, что Vim - не современный инструмент, а популярность его поддерживается лишь благодаря старичкам и тем, кто любит выпендриваться.

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

Главный аргумент в пользу вима -Vim позволяет писать эффективно

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

Этой же цели цели хочу добиться я. Но без привязки к Виму, с его недружелюбными режимами.

Используем AHK

AutoHotkey свободно распространяемый язык для автоматизации выполнения задач в Microsoft Windows. AutoHotkey является языком программирования сценариев, приспособленным к легкому назначению и переназначению горячих клавиш, включая кнопки мыши и джойстика.

Короче говоря, AHK позволяет нам автоматизировать рутинные задачи, создавать программы с графическим интерфейсом или просто автоматически писать Sincerely Yours в конце электронного письма. Чтобы профессионально лениться с помощью AHK нужно существенно поработать головой перед этим.

На обычной клавиатуре зачастую есть такая замечательная, очень бесполезная клавиша, какCapsLock. Почему бесполезная? Да потому что единственная ее функция - зажимать вместо вас клавишуShift. Ее любят в основном тролли в интернете и те, кто часто пишут SQL запросы. Зато неудобств от нее куча. Сколько раз вы проверяли, включен ли у васCapsLockперед вводом пароля? Как минимум раз так точно, а этого уже достаточно, чтобы ночью видеть кошмары.

Вердикт - "капсу" можно найти лучшее применение.

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

Вот как выглядит часть моегоскриптадля AutoHotkey

SetCapsLockState AlwaysOff; Basic movementCapsLock & j::Send {blind}{Left}CapsLock & l::Send {blind}{Right}CapsLock & i::Send {blind}{Up}CapsLock & k::Send {blind}{Down}; Fast moveCapsLock & u::Send {blind}{Up 5}CapsLock & n::Send {blind}{Down 5}; Fast deleteCapsLock & Backspace::Send {blind}{Backspace 5}CapsLock & Delete::Send {blind}{Delete 5}; Delete wordsCapsLock & w::Send {blind}^{Backspace}CapsLock & e::Send {blind}^{Delete}

А вот что он делает

capsKeys keyboard layoutcapsKeys keyboard layout

Если в Vim сочетания клавиш опираются на семантику, то в этом скрипте я опирался на удобство.

Чтобы попробовать, вы можете:

или

Если еще не поняли, то рассказываю в чем суть: когда этот скрипт работает, ничего не меняется до тех пор, пока вы не зажмете клавишу CapsLock. С этого момента начинается магия. Какая? Рассказываю.

Особенности

Никакого больше переключения регистра.Строчные буквы по умолчанию! Это которые маленькие.

Кнопки перемещения находятся в области правой руки.Мы привыкли, что стрелочки справа, поэтому и кнопки навигации - справа.

  • Caps+J- влево

  • Caps+i- вверх

  • Caps+L- вправо

  • Caps+K- вниз

  • Caps+U- вверх пять раз

  • Caps+N- вниз пять раз

  • Caps+Y- страница вверх (PgUp)

  • Caps+B- Страница вниз (PgDn)

Зажатый капс работает как Ctrl в случае с символами X, C, V.Так просто удобнее!

Вызов контекстного меню.Caps + P- позволяет вызвать контекстное меню. Очень полезная комбинация.

Перемещаемся по словамЧерезCaps+LeftAltиCaps+Space. Одно из самых часто используемых мной сочетаний, особенно вместе с зажатым Shift. Однако здесь есть недостаток. Так как мы затрагиваем функциональную клавишу, это меняет поведение Alt. Например, мы хотим использовать сочетаниеAlt+Upв VSCode и делаем это конечно же через AHK. То естьCaps+Alt+Up, но вот проблема, как только мы зажимаем первые две клавиши, все идет к чертям. Что делать? Тут есть два варианта. Можно использовать правый Alt то естьCaps+RightAlt+Upили сначала нажимать Alt а потом остальную часть сочетания.

Удаляем эффективноВы знали, что сочетаниеCtrl+Backspace,Ctrl+Deleteудаляет целые слова вместо символов? Я тоже, до недавнего времени. В скрипте есть целая линия клавиш выделенная для удаления.

  • Caps+Q- удалить все символы слева от курсора

  • Caps+W- удалить слово слева от курсора

  • Caps+E- удалить слово справа от курсора

  • Caps+R- удалить все символы справа от курсора

Фишки

  • Caps+A- Скопировать текущую строку и вставить снизу

  • Caps+S- Выделить слово на позиции курсора

  • Caps+D- Скопировать строку и удалить. Украдено прямиком из вима.

Работает вездеРаботает как в вашем редакторе кода, так и в любом другом текстовом поле. Запомнил один раз - пользуйся везде.

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

Прежде чем основательно начать пользоваться этим скриптом, убедитесь, что вы владеете хотя-бы слепой восьмипальцевой печатью. В противном случае вы рискуете получить вредные привычки, которые будут замедлять вашу скорость набора текста. Советую режим "фразы" вэтомзамечательном бесплатном тренажере.

VSCode

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

VSCode - опенсорсное творение Microsoft, написанное при помощи фреймворков для JavaScript/TypeScript. Из коробки это простенький красивый редактор кода, который позволит вам в считанные секунды начать писать что вздумается. А если прикрутить к нему расширения, которые регулярно пишутся и поддерживаются огромным сообществом, то то эта малышка даст жару любой профессиональной IDE.

Навигация

Ctrl+Bоткрыть / закрыть боковую панель.

Ctrl+Shift+E- открыть меню навигации.

Ctrl+Shift+D- открыть меню запуска. Используется во время дебаггинга.

Ctrl+Shift+Fменю поиска. Позволяет искать текст по всем файлам.

Ctrl+Shift+H- открыть меню замены. Брат Ctrl+Shift+F, но с функцией замены.

Ctrl+Shift+G- открыть меню контроля версий. Если у вас установлено расширение GitLens, то оно может изменить это сочетание.

Ctrl+J- открыть/закрыть панель.

Ctrl+Shift+X- открыть меню расширений.

Ctrl+(backtick)- открыть терминал.

Ctrl+Shift+M- открыть панель ошибок.

Ctrl+Shift+U- открыть консоль вывода.

Ctrl+Shift+Y- открыть консоль отладки.

Простые сочетания

F1- открыть окошко команд. Наше все для пользователя VSCode. Почти любое действие можно выполнить с помощью этого окна.

F2переименовать определение / переменную / функцию синхронно. Одна из самых приятных возможностей в VSCode. Если вы передумали с названием переменной, это позволит изменить все места где используется эта переменная, учитывая контекст.

F8- переместиться к следующему проблемному месту в коде.

Ctrl+.- быстрое исправление ошибки. Если вы допустили какую-то распространенную ошибку, VSCode может исправить ее за вас. Очень удобно использовать в сочетании сF8.

F9- поставить точку остановки для дебаггера.

Ctrl+P- перейти к файлу.

Ctrl+R- открыть недавний проект / файл.

Ctrl+(,)- открыть настройки редактора.

Ctrl+Q- перейти в другую панель.

Ctrl+/- закомментировать строку.

Ctrl+T- переместиться к функции или переменной во всех файлах.

Ctrl+Shift+Oпереместиться к функции или переменной в текущем файле.

Ctrl+Home- переместиться к началу файла.

Ctrl+End- переместиться к концу файла.

Ctrl+Shift+\переместиться к соответствующей скобке.

Ctrl+Shift+N- открыть новое окно VSCode.

Alt+Left/Alt+Rightпереместиться к предыдущей / следующей активной строке. Когда вы скачете со строки на строку, VSCode запоминает это в своей истории, и вы можете быстро переключаться между самыми горячими местами в коде.

Alt+Up/Down- переместить строку вверх/вниз. Must have!

Alt- ускорить прокрутку страницы. Если начать прокручивать страницу и зажать Alt, то процесс пойдет немного быстрее.

Alt+Z- переключить режим переноса строк.

Shift+Alt+F- автоматическое форматирование текста. VSCode поддерживает автоматическое форматирование для большинства языков. Нажатие этой клавиши подгонит ваш код под стандарты, принятые в Code style вашего языка.

Shift+Alt+O- упорядочить импорты в соответствии со стандартами вашего языка.

Ctrl+C- скопировать текущую строку, если нет выделения, иначе работает как обычное копирование.

Ctrl+X- вырезать строку, если нет выделения, иначе работает как обычная операция Cut.

Ctrl+Shift+Up/Down- скопировать выделенные строки вверх/вниз. Полезно, если вам нужно повторить какой-то блок кода несколько раз.

Ctrl+Alt+Right- переместить активный файл в соседнюю группу редактирования. Это позволит вам параллельно просматривать два или более файлов.Ctrl+Alt+Leftдвигает его обратно.

Ctrl+0- фокус на боковую панель.

Ctrl+{1, 2, 3, ..}- фокус на первую/вторую/третью группу редакторов. Если вы параллельно просматриваете два или больше файлов, это сочетание поможет вам переключаться между ними. Однако по своему опыту скажу, что больше двух редакторов никто обычно не открывает. Поэтому у себя я поменял сочетание для работы с двумя окнами редактирования и двумя терминалами.

Alt+{1, 2,..., 8}- переключиться между активными вкладками в окне редактирования. Обязательно к запоминанию!Alt+0открывает последнюю вкладку.

Ctrl+Space- активировать автоподстановку.

Shift+Ctrl+Space- открыть подсказку для параметров функции.

Посложнее

Alt+Ctrl+Up/Down- добавить курсор на верхнюю/нижнюю строку. Одна из особенностей современных редакторов. Позволяет редактировать текст одновременно в нескольких местах. Суперфича!

Ctrl+D- добавить курсор в конец следующего вхождения данного слова.

Alt+Click- добавить курсор в позицию указателя мыши.

Shift+Alt+(Dragging)- добавлять курсоры по пути следования указателя мыши.

Shift+Alt+Right- выделение с учетом контекста. Например, у нас есть длинное выражение внутри скобок, данное сочетание позволит нам выбрать все, что находится внутри них. Последовательные нажатия расширяют область выделения.

Shift+Alt+Left- действие, противоположное Shift+Alt+Right.

Ctrl+Shift+[- свернуть блок кода. Если файл стал слишком большим, и перемещаться стало слишком сложно, то данное сочетание позволит свернуть блоки текста, которые вам сейчас не нужны.

Ctrl+Shift+]- развернуть блок кода. Противоположно Ctrl+Shift+[.

Следующее сочетание отсутствует в сборке для Windows, но я рекомендую установить его вручную. У меня этоCtrl+Shift+J.

Нет(Win) /Ctrl+J(Mac) - присоединить следующую строку к текущей. По сути, все, что делает данная команда, так это удаляет символ переноса с текущей строки. Очень удобно, если вдруг нужно сжать html файл или еще что-то.

Ctrl+Shift+L- выделить все одинаковые слова и переместить курсор к концу каждого. Сильная штука, позволяет редактировать все вхождения определенного слова. Но стоит быть аккуратнее, если это слово встречается в качестве подстроки, то оно тоже будет изменено.

Ctrl+K Z- Включить Zen Mode. Для настоящих гуру.

Демонстрация

Ну и на десерт, небольшое видео, где я наглядно показываю, как можно совместить использование скрипта capsKeys и возможности редактора VSCode. Чудес не обещаю, но суть должна быть понятна.

Заключение

В этой статье я рассмотрел способы увеличения продуктивности при написании кода или любого текста посредством использования сочетания клавиш и кое-чего еще. Мы начали с самых простых сочетаний и дошли до продвинутых вариантов использования клавиатуры. Я надеюсь эти знания не раз пригодятся вам в вашей профессиональной карьере.

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

Пишите в комментариях, если у вас есть свои любимые сочетания, не описанные в статье.

Также, если у вас есть идеи по поводу улучшения скрипта для AutoHotkey, буду рад видеть ваши pull request-ы настранице репозитория.

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

Полезные ссылки

Подробнее..

Как получить гражданство другой страны и не потратить на это 10 лет?

11.04.2021 20:17:45 | Автор: admin

Герои наших статей переезжают вдругие страны порабочей визе иостаются там нанесколько лет, получив ВНЖ или ПМЖ. Ачто насчёт гражданства? Попробовали разобраться (это было непросто), вкаких государствах ипри каких условиях можно получить гражданство впервые годы проживания. Приходите вкомментарии ирассказывайт про свой опыт, будем дополнять иобновлять статью. Осторожно, много юридических терминов.






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


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



Зачем вообще получать именно гражданство


Что обычно дает получение гражданства другого государства?


  • Бессрочный статус свозможностью передавать его понаследству будущим поколениям.
  • Право жить, работать иучиться натерритории страны или других стран, скоторыми заключены особые соглашения.
  • Посещение большего количества стран без визы или наособых условиях. Например, карибская виза позволяет получить туристическую визу вСША на10лет споследующей пролонгацией.


Как получить иностранное гражданство


Начнем стого, что для официального пребывания натерритории страны втечение длительного срока есть следующие документальные формы:


  • Временный вид нажительство (ВНЖ) документ, удостоверяющий личность иностранного гражданина, выдается сроком на1год спродлением до5инеимеет ограничений навъезд встрану. Понему можно учиться, открывать бизнес, новозможности устроиться наработу без дополнительного соглашения оннедает, хотя иможет быть выдан наосновании имеющегося трудового договора слокальной организацией.
  • Постоянный вид нажительство (ПМЖ) документ, подтверждающий личность иностранца. Выдается через несколько лет проживания встране, после ВНЖ, насрок 25+лет, дает право проживать натерритории государства иучаствовать вэкономической деятельности.
  • Гражданство это паспорт гражданина государства, дается либо порождению, либо приобретается несколькими способами. Это бессрочное право жить, работать, перемещаться, получать льготы отгосударства иголосовать.

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


Иммиграционная политика часто корректируется взависимости оттого, желательныли иммигранты встране, какие ивкаком количестве. Например, в2020 году Кипр приостановил выдачу ВНЖ заинвестиции.


Кроме рождения встране, официальных способов получить непросто вид нажительство (ВНЖ), который обеспечивает рабочая или учебная виза, апостоянное место жительства (ПМЖ) изатем гражданство, вбольшинстве стран пять:


  1. Репатриация выдача паспорта гражданина через восстановление родственных связей.
  2. Натурализация получение статуса гражданина после многолетнего ПМЖ, при условии сдачи экзаменов ивыполнения требований кпостоянному проживанию встране.
  3. Инвестиции вэкономику государства поспециальной программе, вряде стран эти инвестиции возвратные.
  4. Покупка недвижимости наопределенную сумму.
  5. Официальный брак спредставителем государства.

Если брак иналичие родственников вжелаемой стране истории глубоко личные, мырассмотрим массовые способы получить паспорт других государств вмаксимально короткие сроки натурализацию иинвестиции. Суммы, которые нужно вложить вгосударственные фонды ивнедвижимость, вбольшинстве случаев кажутся астрономическими, измеряются сотнями тысяч имиллионами евро, ипофакту мало кому доступны. Если высчастливчик, добро пожаловать под кат.





Где получить гражданство за инвестиции

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


Для получения гражданства через инвестиции нужно пройти процедуру Due Diligence или проверку наблагонадежность, где учитывают соблюдение следующих требований состороны потенциального резидента:


  • подтверждение личности;
  • отсутствие судимости;
  • подтверждение легальности получаемого дохода;
  • подтверждение прав нанедвижимость;

Если есть какие-то сложности сдоказательством легальности полученных средств вгражданстве через инвестиции будет отказано.


Для более быстрого получения второго паспорта, от1года, вмире на2021 год действуют 22программы ВНЖ и12программ выдачи гражданства вобмен наинвестиции. ВЧерногории программа заканчивается в2021году.





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



Мальта


Программа получения гражданства заинвестиции наМальте считается одной изнаиболее прогрессивных, здесь ненужно годами продлевать ВНЖ, ауже впервый год получить паспорт.


Сроки получения через инвестиции


C2020 года получить гражданство Мальты можно втечение 13 лет, попрограмме инвестиций через процедуру натурализации заособые заслуги. Согласно мальтийскому законодательству, претенденты награжданство должны получить карту резидента (ВНЖ) ивладеть ейвтечение 12месяцев. Кандидатам напаспорт Мальты выдается электронная карта резидента мальтийское удостоверение личности eResidence card.


Сроки получения через натурализацию


Понимаем, что миллионы евро насчетах есть далеко неукаждого желающего переехать наМальту. Способ получить гражданство понатурализации без инвестиций также возможен, ноонуже далеко нетакой радужный. Подать заявление намальтийское гражданство можно только через 8лет непрерывного проживания поВНЖ запериод от12лет. При этом нужно подтвердить знание английского имальтийского языков идоказательство своей практической пользы для государства дипломы специалиста, рекомендательные письма ипр.


Объем инвестиций


Чтобы стать гражданином этого островного государства, инвестору необходимо перечислить 690тыс.вФонд национального исоциального развития страны, атакже приобрести недвижимость стоимостью неменее 350тыс.ивложиться воблигации (неменее 150тыс. сроком напять лет). Вобщей сложности кандидату придется потратить больше 1млн.


Сдача экзамена


Заинвестиции непредусмотрена. Понатурализации требуется подтверждение знания английского имальтийского языков.


Необходимость проживания встране


Для получения гражданства заинвестиции постоянное проживание встране нетребуется, подать иоформить документы можно удаленно. Понатурализации проживание неменее 8лет.


Возможность проживания вдругих странах


Гражданин Мальты получает право безвизово въезжать в182 страны мира, включая ЕС, Великобританию, США иКанаду. Атакже жить иработать в28странах ЕС.



Португалия


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


Объем инвестиций


Португальская миграционная программа Золотая виза (Golden Residence Permit) включает три варианта условий получения ВНЖ споследующим получением гражданства. Первое нужно приобрести вПортугалии недвижимость насумму от500тыс., второе перевести насчёт португальского банка неменее 1млн, итретье создать встране десять постоянных рабочих мест.


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


Сроки получения через инвестиции


Получить ВНЖ можно всего заодно посещение страны, рассмотрение документов занимает приблизительно два месяца. Через год можно продлить ВНЖ надва последовательных срока подва года каждый. Ачерез пять лет временный вид нажительство можно сменить напостоянный иещё через год претендовать награжданство. Тоесть, срок получения гражданства составит 6лет.



Греция


Одна изстран свыгодными условиями для получения ВНЖ ипоследующего получения гражданства через 7лет.


Сроки получения


ВНЖ выдают втечение 3месяцев. Срок возврат инвестиций 5лет. Гражданство наосновании инвестиций можно получить через 7лет при подаче заявления исохранения инвестиций встране. При натурализации срок получения гражданства от12лет.


Стоимость инвестиций


Греческая программа Greece Golden Visa Programme пополучению вида нажительство при покупке или аренде недвижимости на5лет стоит 250,000. Второй вариант это депозит или акции греческих компаний на400,000. Дополнительно оплачивается заявление наполучение золотой визы вГреции 2,000 для основного инвестора и150 для членов семьи.


Необходимость проживания встране


При получении ВНЖ игражданства поинвестиционной программе требований кпроживанию встране нет. Нужно только один раз приехать, чтобы оставить вмиграционной службе биометрические данные. Документ нетребует регулярного продления, кроме проверки наличия инвестиций раз в5лет.


Сдача экзамена


Экзамен наполучение гражданства вГреции предусмотрен как для инвесторов, так идля тех, кто планирует получить паспорт понатурализации.


16мая 2021 года пройдет первый письменный экзамен для желающих получить гражданство Греции понатурализации. Экзамен проверяет уровень владения греческим языком, знание истории, культуры, географии исистемы управления страны. Рассказываем оновых правилах получения греческого паспорта. Стоимость пошлины засдачу экзамена 150.


Раньше иностранцы сдавали только устный экзамен награжданство. Его принимали комитеты понатурализации. Собеседование длилось около получаса. Поновым правилам иностранец сдает два экзамена: письменный, апотом устное собеседование. Письменный экзамен позволит более объективно оценивать претендентов награжданство. Подход коценке будет единым всоответствии состандартами панэллинских экзаменов.


Возможность проживания вдругих странах


Свободный выезд ипроживание встранах ЕС.



Карибские государства (Сент-Китис, Невис, Антигуа, Гренада)


Интересное предложение для тех, кому важно максимально быстро получить зарубежное гражданство страны Карибского бассейна.


Сроки получения


46 месяцев


Объем инвестиций


ВАнтигуа иГренаде, Сент Китс иНевис единовременное безвозвратное дотационное пожертвование вФонд национального развития страны наминимальную сумму от100,000 долларов США позволяет иностранцу претендовать напаспорт Карибского бассейна. Впрограмме можно участвовать семьей, сдоплатой закаждого члена семьи.


Можно также участвовать вгосударственной программе инвестиций внедвижимость.Чтобы получить паспорт, необходимо инвестировать впредварительно утвержденный девелоперский проект сумму более 200, 000 долларов США, свозможностью продать актив через 7лет, или более 400,000долларов, свозможностью продать недвижимость через 5лет для каждого основного заявителя.


Дополнительно после утверждения кандидатуры нужно оплатить единовременный государственный сбор вразмере 35,047 долларов для основного заявителя, 20,047 долларов для супруга и10,047 долларов для всех прочих иждивенцев основного заявителя, независимо отихвозраста. Атакже расходы заподачу документов от1,000 долларов счеловека.





Сдача экзамена


Нетребуется.


Необходимость проживания встране


Гражданство стран Карибского бассейна: Сент-Китса иНевиса, Антигуа иБарбуды, Доминиканы иГренады получить удаленно, без необходимости посещать страну.


Возможность проживания вдругих странах


Безвизовый режим при въезде в130 + стран, включая государства Шенгенского соглашения, Великобританию, США ибольшую часть Южной Америки.




Вбольшинстве случаев IT-специалисты для релокации выбирают страны Европы, США иКанаду, где наполучение паспорта гражданина внекоторых странах может потребоваться неменее 10лет проживания ивыполнение многих других условий. Нонеотчаивайтесь! Если это ваша цель, есть государства, где получить заветный паспорт немного проще.



Страны слояльными условиями получения гражданства путем натурализации


Самый доступный способ получения гражданства сточки зрения финансов натурализация. Человек загоды проживания полностью ассимилируется встране идолжен только подтвердить свое соответствие статусу гражданина: спомощью экзамена исоблюдения ряда требований. Экзамен может включать всебя знание культуры, истории, гимна страны пребывания, авкачестве особых требований может потребоваться даже отказ отпервого гражданства. Наэтот способ уйдет от5лет постоянного пребывания встране.


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





Кипр


Доноября 2020 года Кипр был одной изнаиболее интересных стран пополучению гражданства заинвестиции. Его выдавали уже втечение 3месяцев при вложении 2


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


Сроки получения гражданства через натурализацию


Для подачи заявления награжданство требуется инепрерывное проживание поВНЖ неменее 7лет, пакет документов, переведенный нагреческий или сапостилем, выписка околичестве прожитых наКипре лет.


Сдача экзамена


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


Необходимость проживания встране


Непрерывно нужно прожить натерритории государства от7лет из8, причем последние 365 дней перед подачей заявления никуда невыезжая.


Возможность проживания вдругих странах


Паспорт киприота дает все права гражданинаЕС, включая свободное проживание иперемещение вэтих странах.





Швеция


Вэтой Скандинавской стране приоритет гражданство покрови. Для граждан других стран путь получения шведского паспорта натурализация. Иотказываться отсвоего первого гражданства здесь нетребуется.


Сроки получения гражданства через натурализацию


Для подачи заявления награжданство требуется непрерывное проживание поВНЖ втечение 5лет. Для граждан других скандинавских стран 2года, для беженцев, неимеющих никакого гражданства 4года.


Сдача экзамена


Пока еще Швеция одна изтрёх странЕС, вкоторой для получения гражданства нетребуется доказывать знание местного языка. Претендентам награжданство нужно пройти последний уровень курсов шведского языка для иммигрантов (SFI) или сдать экзамен TISUS, используемый для проверки знания шведского при поступлении вуниверситет.


В2021 году правительство предложило проведение нового общенационального языкового экзамена. Иностранцам предлагается сдать экзамены по4языковым навыкам: разговор, письмо, чтение иаудирование, атакже пройти тест пообществоведению. Для сдачи экзамена нужно будет оплатить сбор заэкзамены вразмере около 300евро, помимо сбора заподачу заявления наполучение гражданства вразмере 180евро. Для устной иписьменной речи иностранец должен будет подтвердить уровень знания языка ненижеA2, адля чтения иаудирования B1.


Необходимость проживания встране


Непрерывно от5лет.


Возможность проживания вдругих странах


Шведское гражданство, как идругое гражданство встранахЕС, предусматривает свободное проживание иперемещение постранам Европы.





Израиль


Для подачи заявления награжданство требуется непрерывное проживание встране, статус ВНЖ, плюсом будет собственное место жительства, атакже документально подтвержденное финансовое обеспечение. Аеще нужно отказаться отсвоего первого гражданства ипринести присягу наверность илояльность израильскому государству. Наиболее выгодные условия дают тем, кто прошел вИзраиле военную службу.


Сроки получения гражданства через натурализацию


От3лет.


Сдача экзамена


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


Необходимость проживания встране


Нужно проживать непрерывно от3лет из5.


Возможность проживания вдругих странах


Для посещения других стран потребуется загранпаспорт ивизы.





Германия


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


Сроки получения гражданства через натурализацию


Для подачи заявления награжданство требуется инепрерывное проживание поВНЖ втечение 8лет.


Сдача экзамена


Предусмотрено тестирование назнание национальной культуры, истории, права иполитического устройства государства. Кроме того, нужно предоставить результаты теста назнание языка уровня нениже B1.


Необходимость проживания встране


Непрерывно от8лет.


Возможность проживания вдругих странах


Гражданство Германии дает право жить исвободно перемещаться повсем государствам ЕС.





Португалия


Через 5лет постоянного проживания встране можно подать заявку наполучение гражданства исдать экзамен.


Необходимость проживания встране


Попрограмме натурализации нужно проживать встране неменее 183 дней вгоду.


Сдача экзамена


При натурализации перед подачей документов награжданство нужно сдать экзамен CILPE.


Всоответствии сзаконодательством, кандидат, который претендует наполучение португальского гражданства, должен продемонстрировать уровень владения португальским языком A2или выше.


Соответственно, для получение португальского гражданства можно сдать экзамены CILPE, DEPLE, DIPLE, DAPLE или DUPLE. Для получения гражданства Португалии неподходит только экзамен ACESSO, так как онсоответствует уровню А1.


Возможность проживания вдругих странах


Гражданство Португалии дает право свободно проживать, учиться иработать встранах ЕС.





Турция


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


Сроки получения гражданства через натурализацию


Для этого нужно встатусе ВНЖ прожить натерритории страны 5лет.


Сдача экзамена


Нужно сдать экзамен ипри подаче заявления предоставить сертификат ознании турецкого языка. Атакже заявитель проходит собеседования, где просят рассказать осебе натурецком языке, атакже окультуре иполитике страны.


Необходимость проживания встране


Прожить встране нужно неменее 5лет, инепокидать страну втечение 3месяцев доподачи заявления наполучение гражданства. Срок рассмотрения заявления 6-18 месяцев.


Возможность проживания вдругих странах


Безвизовый въезд в110 государств мира, включая Японию иКорею.





Исландия


Здесь относительно комфортные условия для получения паспорта. Важно иметь законные источники дохода иненарушать местные правила изаконы.


Сроки получения гражданства через натурализацию


Чтобы получить гражданство натерритории островного государства нужно прожить неменее 7лет. Срок рассмотрения заявления 12месяцев.


Сдача экзамена


Нужно сдать экзамен назнание исландского языка.


Необходимость проживания встране


Постоянно проживать встране 7лет.


Возможность проживания вдругих странах


Обладатели исландского паспорта могут посещать без визы 160 стран мира.





Великобритания


Страна туманного альбиона, как нистранно, очень лояльна киммигрантам, желающим стать гражданами королевства. Натурализация один изосновных методов получения паспорта.


Сроки получения гражданства понатурализации


Для подачи заявления награжданство нужно прожить натерритории страны 6лет, 5изкоторых встатусе ПМЖ. Рассмотрение заявки наполучение гражданства занимает 67 месяцев.


Сдача экзамена


Необходимо сдать экзамен ввиде теста назнание культуры иполитики страны. Нужно также пройти процедуру дачи клятвы верности стране иполучить сертификат онатурализации. Только после этого будет выдан паспорт.


Необходимость проживания встране


Заявитель должен прожить встране неменее 12месяцев после получения ПМЖ. Если доподачи заявки награжданство заявители провели запределами Великобритании более 2лет, статус резидента (ПМЖ) может быть аннулирован.


Возможность проживания вдругих странах


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


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


Стоимость исроки могут вразы отличаться, понатурализации неменее 5лет. Оформление документов насебя ичленов семьи вмиграционной службе также обойдется внесколько тысяч долларов или евро.


Важно еще доподачи заявления награжданство учесть все требования экзамен, время проживания встране, положительные итоги предварительной проверки документов Due Diligence.


Все это поможет избежать отказа иполучить гражданство вустановленные законом государства сроки.



Полезные ссылки



<рекламная пауза>Найти работу зарубежом вжелаемой стране проживания вам поможет телеграм-бот @g_jobbot. Трудовой контракт вIT-компании поможет без проблем получить ВНЖ. </рекламная пауза>
Подробнее..

Категории

Последние комментарии

© 2006-2021, personeltest.ru