<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vadik</title>
    <description>The latest articles on DEV Community by Vadik (@sbeuvadyarik67).</description>
    <link>https://dev.to/sbeuvadyarik67</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3974581%2F4999f959-88ec-4928-beac-6f67bc4b8fd4.jpeg</url>
      <title>DEV Community: Vadik</title>
      <link>https://dev.to/sbeuvadyarik67</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sbeuvadyarik67"/>
    <language>en</language>
    <item>
      <title>Как я собрал 4 проекта в один .exe — и почему это плохая идея</title>
      <dc:creator>Vadik</dc:creator>
      <pubDate>Sun, 13 Sep 2026 14:50:27 +0000</pubDate>
      <link>https://dev.to/sbeuvadyarik67/kak-ia-sobral-4-proiekta-v-odin-exe-i-pochiemu-eto-plokhaia-idieia-1fi0</link>
      <guid>https://dev.to/sbeuvadyarik67/kak-ia-sobral-4-proiekta-v-odin-exe-i-pochiemu-eto-plokhaia-idieia-1fi0</guid>
      <description>&lt;h1&gt;
  
  
  Как я собрал 4 проекта в один .exe — и почему это плохая идея
&lt;/h1&gt;

&lt;p&gt;Привет, Хабр!&lt;/p&gt;

&lt;p&gt;У меня есть четыре пет-проекта на Python: &lt;strong&gt;NeoBrain (локальный AI-чат)&lt;/strong&gt;, &lt;strong&gt;NeoSpace OS (виртуальная среда)&lt;/strong&gt;, &lt;strong&gt;NeoReceipt (генератор чеков)&lt;/strong&gt; и &lt;strong&gt;Why Does This Exist? (интерактивная панель)&lt;/strong&gt;. Каждый — отдельный &lt;code&gt;.py&lt;/code&gt; файл со своим GUI.&lt;/p&gt;

&lt;p&gt;Запускать их было неудобно: открываешь терминал, пишешь &lt;code&gt;python neobrain.py&lt;/code&gt;, потом закрываешь, потом &lt;code&gt;python neoreceipt.py&lt;/code&gt;… В общем, боль.&lt;/p&gt;

&lt;p&gt;Я решил сделать лаунчер — одно окно с карточками проектов, кнопка «Запустить» — и всё работает. И вот тут начались грабли, о которых я хочу рассказать.&lt;/p&gt;

&lt;h2&gt;
  
  
  Первая версия: наивная сборка
&lt;/h2&gt;

&lt;p&gt;Сделал я лаунчер на &lt;strong&gt;Tkinter&lt;/strong&gt; (просто, быстро, встроено в Python). Выглядит вот так:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7msggc3d5mtn875p3tpv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7msggc3d5mtn875p3tpv.png" alt="Скриншот лаунчера" width="800" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Дальше — сборка в &lt;code&gt;.exe&lt;/code&gt; через &lt;strong&gt;PyInstaller&lt;/strong&gt;. Хотелось один файл, чтобы пользователь скачал и запустил, без установки Python и зависимостей.&lt;/p&gt;

&lt;p&gt;Написал &lt;code&gt;.spec&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Analysis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;launcher.py&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;datas&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;manifest.json&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;projects&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;projects&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Что это значит: &lt;code&gt;manifest.json&lt;/code&gt; и папка &lt;code&gt;projects/&lt;/code&gt; &lt;strong&gt;вшиваются&lt;/strong&gt; внутрь &lt;code&gt;.exe&lt;/code&gt;. Всё в одном файле. Красиво же?&lt;/p&gt;

&lt;p&gt;Собрал. Размер — около &lt;strong&gt;20 МБ&lt;/strong&gt;. Запустил. Работает. Карточки есть, кнопки нажимаются, проекты открываются. Я был доволен.&lt;/p&gt;

&lt;h2&gt;
  
  
  Проблема
&lt;/h2&gt;

&lt;p&gt;Через пару дней я обновил &lt;strong&gt;NeoBrain&lt;/strong&gt; — добавил пару фич, поправил баги. Запускаю лаунчер, жму «Запустить NeoBrain» — открывается &lt;strong&gt;старая версия&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Почему?&lt;/strong&gt; Потому что &lt;code&gt;.exe&lt;/code&gt; вшил в себя старую версию &lt;code&gt;neobrain.py&lt;/code&gt; ещё при сборке.&lt;/p&gt;

&lt;p&gt;Чтобы обновление сработало, надо:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Пересобрать &lt;code&gt;.exe&lt;/code&gt; (30-60 секунд).&lt;/li&gt;
&lt;li&gt;Получить новый файл на &lt;strong&gt;20 МБ&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Залить его в релиз.&lt;/li&gt;
&lt;li&gt;Пользователь скачивает &lt;strong&gt;20 МБ&lt;/strong&gt; ради одного изменённого &lt;code&gt;.py&lt;/code&gt; (в котором &lt;strong&gt;50 КБ&lt;/strong&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;И так — &lt;strong&gt;каждый раз&lt;/strong&gt;, при &lt;strong&gt;любом&lt;/strong&gt; обновлении &lt;strong&gt;любого&lt;/strong&gt; проекта.&lt;/p&gt;

&lt;p&gt;Я подумал: «Это же абсурд. Пользователи будут качать &lt;strong&gt;гигабайты&lt;/strong&gt; ради &lt;strong&gt;килобайтов&lt;/strong&gt; изменений».&lt;/p&gt;

&lt;h2&gt;
  
  
  Решение: не вшивать данные
&lt;/h2&gt;

&lt;p&gt;Я убрал &lt;code&gt;datas=[...]&lt;/code&gt; из &lt;code&gt;.spec&lt;/code&gt;. Оставил &lt;code&gt;datas=[]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Теперь &lt;code&gt;.exe&lt;/code&gt; — &lt;strong&gt;только лаунчер&lt;/strong&gt;. Проекты и &lt;code&gt;manifest.json&lt;/code&gt; — &lt;strong&gt;рядом&lt;/strong&gt; с ним, в папке:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NeoLauncher/
├── NeoLauncher.exe       ← 10 МБ, только лаунчер
├── manifest.json         ← список проектов
└── projects/
    ├── neobrain.py
    ├── neospace.py
    ├── neoreceipt.py
    └── whydoes.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Плюсы:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Обновил &lt;code&gt;neobrain.py&lt;/code&gt; → просто заменил файл. Exe &lt;strong&gt;не трогаешь&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Пользователь качает &lt;strong&gt;только изменённый &lt;code&gt;.py&lt;/code&gt;&lt;/strong&gt; (килобайты), а не 10 МБ.&lt;/li&gt;
&lt;li&gt;Можно &lt;strong&gt;добавлять новые проекты&lt;/strong&gt; — просто положил &lt;code&gt;.py&lt;/code&gt; в &lt;code&gt;projects/&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Казалось бы — идеально. Но была &lt;strong&gt;одна проблема&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Вторая проблема: exe не находит manifest.json
&lt;/h2&gt;

&lt;p&gt;Собрал новый &lt;code&gt;.exe&lt;/code&gt;. Запускаю. &lt;strong&gt;«❌ Нет проектов»&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Почему? Потому что в коде у меня было:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abspath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__file__&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;manifest_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base_dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;manifest.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;__file__&lt;/code&gt; — это &lt;strong&gt;сам &lt;code&gt;launcher.py&lt;/code&gt;&lt;/strong&gt;. Когда запускаешь &lt;strong&gt;как скрипт&lt;/strong&gt; — всё ок, &lt;code&gt;manifest.json&lt;/code&gt; рядом. Но когда запускаешь &lt;strong&gt;как &lt;code&gt;.exe&lt;/code&gt;&lt;/strong&gt;, &lt;code&gt;__file__&lt;/code&gt; указывает на &lt;strong&gt;временную папку PyInstaller&lt;/strong&gt; (&lt;code&gt;%TEMP%\_MEIxxxxx\&lt;/code&gt;), а не на папку с exe.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Итог:&lt;/strong&gt; лаунчер ищет &lt;code&gt;manifest.json&lt;/code&gt; &lt;strong&gt;не там, где нужно&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Решение: sys.frozen
&lt;/h2&gt;

&lt;p&gt;PyInstaller устанавливает флаг &lt;strong&gt;&lt;code&gt;sys.frozen = True&lt;/code&gt;&lt;/strong&gt;, когда приложение запущено &lt;strong&gt;как собранный exe&lt;/strong&gt;. Это можно использовать:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;frozen&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Запущено как .exe — папка рядом с exe
&lt;/span&gt;    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;executable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Запущено как .py — папка скрипта
&lt;/span&gt;    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abspath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__file__&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Что даёт:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;В режиме &lt;code&gt;.py&lt;/code&gt; — папка скрипта (как раньше).&lt;/li&gt;
&lt;li&gt;В режиме &lt;code&gt;.exe&lt;/code&gt; — папка с exe (там, где &lt;code&gt;manifest.json&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Пересобрал. Запускаю. &lt;strong&gt;«✦ 4 ПРОЕКТОВ ГОТОВЫ К ЗАПУСКУ»&lt;/strong&gt;. Карточки на месте. Кнопки работают.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1qpxn13xtibmh2nreko0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1qpxn13xtibmh2nreko0.png" alt="Скриншот работающего лаунчера" width="662" height="750"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Что получилось в итоге
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;NeoLauncher v2.0.0:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.exe&lt;/code&gt; — &lt;strong&gt;10 МБ&lt;/strong&gt; (только лаунчер).&lt;/li&gt;
&lt;li&gt;Проекты — &lt;strong&gt;рядом&lt;/strong&gt;, обновляются &lt;strong&gt;независимо&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Релиз на &lt;strong&gt;GitHub Releases&lt;/strong&gt;: пользователь качает &lt;code&gt;.zip&lt;/code&gt; → распаковывает → запускает.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Обновление проекта&lt;/strong&gt; — замена &lt;code&gt;.py&lt;/code&gt; файла, exe &lt;strong&gt;не трогается&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Мораль
&lt;/h2&gt;

&lt;p&gt;Если вы собираете &lt;code&gt;.exe&lt;/code&gt; через PyInstaller и &lt;strong&gt;вшиваете&lt;/strong&gt; в него данные через &lt;code&gt;datas=[...]&lt;/code&gt; — &lt;strong&gt;подумайте дважды&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Как часто&lt;/strong&gt; эти данные &lt;strong&gt;меняются&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Как часто&lt;/strong&gt; вы готовы &lt;strong&gt;пересобирать&lt;/strong&gt; exe?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Готовы ли&lt;/strong&gt; пользователи &lt;strong&gt;качать 10-20 МБ&lt;/strong&gt; ради &lt;strong&gt;килобайтов&lt;/strong&gt; изменений?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Если данные меняются часто&lt;/strong&gt; — &lt;strong&gt;не вшивайте&lt;/strong&gt;. Пусть exe будет &lt;strong&gt;тонким&lt;/strong&gt;, а данные — &lt;strong&gt;рядом&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Используйте&lt;/strong&gt; &lt;code&gt;sys.frozen&lt;/code&gt; для &lt;strong&gt;корректных путей&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;frozen&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;base_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;executable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;base_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abspath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__file__&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Это &lt;strong&gt;сэкономит&lt;/strong&gt; вам &lt;strong&gt;часы пересборок&lt;/strong&gt; и &lt;strong&gt;гигабайты&lt;/strong&gt; пользовательского трафика.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ссылки
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/Sbeuvadyarik67/NeoLauncher-" rel="noopener noreferrer"&gt;github.com/Sbeuvadyarik67/NeoLauncher-&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Releases:&lt;/strong&gt; &lt;a href="https://github.com/Sbeuvadyarik67/NeoLauncher-/releases/latest" rel="noopener noreferrer"&gt;NeoLauncher v2.0.0&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;README:&lt;/strong&gt; в репозитории&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Вопрос к читателям
&lt;/h2&gt;

&lt;p&gt;А вы &lt;strong&gt;вшиваете&lt;/strong&gt; данные в &lt;code&gt;.exe&lt;/code&gt; или &lt;strong&gt;разделяете&lt;/strong&gt;? Сталкивались с похожей проблемой? Расскажите в комментариях — интересно сравнить подходы.&lt;/p&gt;

&lt;p&gt;Спасибо за внимание!&lt;/p&gt;

</description>
      <category>python</category>
      <category>opensource</category>
      <category>github</category>
      <category>tkinter</category>
    </item>
    <item>
      <title>NeoSpace Pro - виртуальная среда</title>
      <dc:creator>Vadik</dc:creator>
      <pubDate>Wed, 24 Jun 2026 17:35:05 +0000</pubDate>
      <link>https://dev.to/sbeuvadyarik67/neospace-pro-virtualnaia-srieda-3eoj</link>
      <guid>https://dev.to/sbeuvadyarik67/neospace-pro-virtualnaia-srieda-3eoj</guid>
      <description>&lt;h1&gt;
  
  
  🧠 NeoSpace Pro — виртуальная среда для Windows на Python
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;NeoSpace Pro&lt;/strong&gt; — это изолированное виртуальное пространство для Windows.&lt;br&gt;&lt;br&gt;
Все файлы хранятся отдельно от реальной системы. Удобно для экспериментов, работы с файлами и тестирования.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✨ Возможности
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🔍 &lt;strong&gt;Поиск файлов&lt;/strong&gt; в реальном времени&lt;/li&gt;
&lt;li&gt;🖱️ &lt;strong&gt;Перетаскивание&lt;/strong&gt; (Drag-and-Drop)&lt;/li&gt;
&lt;li&gt;📥 &lt;strong&gt;Импорт&lt;/strong&gt; и 📤 &lt;strong&gt;Экспорт&lt;/strong&gt; папок&lt;/li&gt;
&lt;li&gt;⏱️ &lt;strong&gt;Таймер&lt;/strong&gt; для автоматического бэкапа и очистки&lt;/li&gt;
&lt;li&gt;📜 &lt;strong&gt;Логирование&lt;/strong&gt; всех действий&lt;/li&gt;
&lt;li&gt;🎨 &lt;strong&gt;Тёмная тема&lt;/strong&gt; интерфейса&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🚀 Запуск
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
bash
pip install tkinterdnd2
python virtual_minimal.py

🛠️ Технологии
Python 3.7+

Tkinter + tkinterdnd2

📂 Ссылка на проект
https://github.com/Sbeuvadyarik67/NeoSpace-Pro

💬 Вопросы и идеи
Если есть пожелания или вопросы — пиши в комментарии или в Issues на GitHub.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>opensource</category>
      <category>python</category>
      <category>showdev</category>
      <category>tooling</category>
    </item>
    <item>
      <title>NeoBrain: как мой open source проект попал в рекомендации Яндекс Алисы</title>
      <dc:creator>Vadik</dc:creator>
      <pubDate>Sat, 13 Jun 2026 19:29:00 +0000</pubDate>
      <link>https://dev.to/sbeuvadyarik67/neobrain-kak-moi-open-source-proiekt-popal-v-riekomiendatsii-iandieks-alisy-3bj1</link>
      <guid>https://dev.to/sbeuvadyarik67/neobrain-kak-moi-open-source-proiekt-popal-v-riekomiendatsii-iandieks-alisy-3bj1</guid>
      <description>&lt;h1&gt;
  
  
  NeoBrain: как мой open source проект попал в рекомендации Яндекс Алисы
&lt;/h1&gt;

&lt;p&gt;Привет, dev.to! 👋&lt;/p&gt;

&lt;p&gt;Пару недель назад я опубликовал свой проект — &lt;strong&gt;NeoBrain&lt;/strong&gt;, локальный аналог Character.AI на базе Ollama. А сегодня... Яндекс Алиса сама начала его рекомендовать!&lt;/p&gt;




&lt;h2&gt;
  
  
  🤖 Что такое NeoBrain
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;NeoBrain&lt;/strong&gt; — это веб-приложение с открытым исходным кодом, которое позволяет:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Создавать ИИ-персонажей с уникальными характерами&lt;/li&gt;
&lt;li&gt;Общаться с ними полностью офлайн&lt;/li&gt;
&lt;li&gt;Настраивать «температуру» ответов (от 1 до 10)&lt;/li&gt;
&lt;li&gt;Менять темы оформления (Космос, Неон, Летняя и другие)&lt;/li&gt;
&lt;li&gt;Копировать ответы в один клик&lt;/li&gt;
&lt;li&gt;Сохранять историю диалогов в браузере&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Бэкенд:&lt;/strong&gt; FastAPI + Uvicorn&lt;br&gt;&lt;br&gt;
&lt;strong&gt;ИИ-движок:&lt;/strong&gt; Ollama (локально)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Фронтенд:&lt;/strong&gt; чистый HTML/CSS/JS&lt;/p&gt;




&lt;h2&gt;
  
  
  🔍 Как Яндекс Алиса нашла NeoBrain
&lt;/h2&gt;

&lt;p&gt;Я не платил за рекламу. Просто выложил код на GitHub, написал статью на dev.to, и... алгоритм Яндекса сам проиндексировал проект.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Что я увидел однажды утром:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7by3wy75i19z401svo73.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7by3wy75i19z401svo73.png" alt=" " width="800" height="773"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;По запросу &lt;em&gt;«Какой есть локальный аналог Character.AI на Ollama?»&lt;/em&gt; Алиса выдаёт:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Название и описание проекта&lt;/li&gt;
&lt;li&gt;✅ Ключевые возможности&lt;/li&gt;
&lt;li&gt;✅ Упоминание открытого кода&lt;/li&gt;
&lt;li&gt;✅ Ссылку на GitHub&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📊 Первая статистика
&lt;/h2&gt;

&lt;p&gt;За короткое время проект получил:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔁 &lt;strong&gt;99 клонов&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;👁️ &lt;strong&gt;400+ просмотров&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;🌐 Переходы из Яндекса и Google&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 Что дальше?
&lt;/h2&gt;

&lt;p&gt;В планах:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Экспорт/импорт персонажей&lt;/li&gt;
&lt;li&gt;Docker-образ для установки в 1 команду&lt;/li&gt;
&lt;li&gt;Telegram-бот на базе NeoBrain&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💬 Обратная связь
&lt;/h2&gt;

&lt;p&gt;Мне очень важно услышать сообщество!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Как вы нашли этот пост?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Что вас заинтересовало в NeoBrain?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Что бы вы хотели добавить или улучшить?&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Пишите в комментариях — я отвечу каждому! 👇&lt;/p&gt;




&lt;h2&gt;
  
  
  🔗 Полезные ссылки
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;📦 &lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/Sbeuvadyarik67/NeoBrain" rel="noopener noreferrer"&gt;https://github.com/Sbeuvadyarik67/NeoBrain&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📄 &lt;strong&gt;Предыдущая статья:&lt;/strong&gt; &lt;a href="https://dev.to/sbeuvadyarik67/neobrain-a-local-alternative-to-characterai-4kj7"&gt;https://dev.to/sbeuvadyarik67/neobrain-a-local-alternative-to-characterai-4kj7&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👤 &lt;strong&gt;Мой VK:&lt;/strong&gt; &lt;a href="https://vk.com/v_rusich007" rel="noopener noreferrer"&gt;https://vk.com/v_rusich007&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Поставьте звезду на GitHub, если проект полезен!&lt;/strong&gt; ⭐&lt;/p&gt;

&lt;p&gt;Спасибо за внимание! 🚀&lt;/p&gt;

</description>
      <category>python</category>
      <category>opensource</category>
      <category>ollama</category>
      <category>chatbot</category>
    </item>
    <item>
      <title>NeoBrain: A Local Alternative to Character.AI</title>
      <dc:creator>Vadik</dc:creator>
      <pubDate>Mon, 08 Jun 2026 17:30:43 +0000</pubDate>
      <link>https://dev.to/sbeuvadyarik67/neobrain-a-local-alternative-to-characterai-4kj7</link>
      <guid>https://dev.to/sbeuvadyarik67/neobrain-a-local-alternative-to-characterai-4kj7</guid>
      <description>&lt;h2&gt;
  
  
  🤔 Проблема
&lt;/h2&gt;

&lt;p&gt;Character.AI хорош, но:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ Заблокирован в некоторых странах&lt;/li&gt;
&lt;li&gt;❌ Требует постоянного подключения к интернету&lt;/li&gt;
&lt;li&gt;❌ Твои диалоги не приватны&lt;/li&gt;
&lt;li&gt;❌ Платные подписки&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 Решение: NeoBrain
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;NeoBrain&lt;/strong&gt; — это локальная, бесплатная альтернатива.&lt;br&gt;&lt;br&gt;
Всё работает на твоём компьютере — полностью офлайн.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/Sbeuvadyarik67/NeoBrain" rel="noopener noreferrer"&gt;GitHub репозиторий&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ✨ Возможности
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Функция&lt;/th&gt;
&lt;th&gt;Описание&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;🤖 &lt;strong&gt;Локальная нейросеть&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Работает через Ollama&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🎭 &lt;strong&gt;Персонажи&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Создавай любых персонажей&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🎨 &lt;strong&gt;7 тем&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Неон, Baby‑doll, Летняя, Пляжная, Цифровая, Творческая, Тёплая&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🌡️ &lt;strong&gt;Температура&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;1 (чётко) → 10 (креативно)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;📋 &lt;strong&gt;Копирование ответов&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;В один клик&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;💾 &lt;strong&gt;История чатов&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Сохраняется в браузере&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🧠 &lt;strong&gt;Потоковые ответы&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Печатает как ChatGPT&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🖼️ Скриншоты
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Главный экран&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0769e755z7uck7k62pfk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0769e755z7uck7k62pfk.png" alt="Главный экран" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Диалог с ИИ&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl40414gg48929a8d6140.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl40414gg48929a8d6140.png" alt="Диалог с ИИ" width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Панель персонажей&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmntqear4p0kzfgzyiykj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmntqear4p0kzfgzyiykj.png" alt="Панель персонажей" width="800" height="668"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ Как это работает
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Бэкенд:&lt;/strong&gt; FastAPI + Uvicorn&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ИИ:&lt;/strong&gt; Ollama (локально)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Фронтенд:&lt;/strong&gt; чистый HTML/CSS/JS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Сервер отправляет запрос в Ollama, нейросеть генерирует ответ, чат обновляется.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Быстрый старт
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
bash
# 1. Установи Ollama
curl -fsSL https://ollama.com/install.sh | sh

# 2. Скачай модель (рекомендуемая для ролевых игр)
ollama pull llama3.1:8b

# 3. Склонируй репозиторий
git clone https://github.com/Sbeuvadyarik67/NeoBrain.git
cd NeoBrain

# 4. Установи зависимости
pip install -r requirements.txt

# 5. Запусти сервер
python main.py

# 6. Открой http://localhost:8000

---

## 💬 Поддержать проект

- ⭐ **Поставь звезду на GitHub** — это помогает проекту расти  
- 🐛 **Нашёл баг?** Создай Issue  
- 💡 **Есть идея?** Напиши в комментариях или в ВК  
- 🔁 **Расскажи друзьям** — локальный ИИ удобно показывать вживую

👉 [GitHub репозиторий](https://github.com/Sbeuvadyarik67/NeoBrain)  
📬 **ВКонтакте:** [v_rusich007](https://vk.com/v_rusich007)

---

*Сделано с 🧠 в России — открытый код, навсегда бесплатно.*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>opensource</category>
      <category>fastapi</category>
      <category>ollama</category>
      <category>aichat</category>
    </item>
  </channel>
</rss>
