<?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: Amir mohamad</title>
    <description>The latest articles on DEV Community by Amir mohamad (@fjfycfgdy).</description>
    <link>https://dev.to/fjfycfgdy</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%2F4139533%2F6815c6f3-b0ed-457a-b257-d6a6ebb13d96.png</url>
      <title>DEV Community: Amir mohamad</title>
      <link>https://dev.to/fjfycfgdy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fjfycfgdy"/>
    <language>en</language>
    <item>
      <title>Building a .pypkg Package Runner for Windows with Python 3.14 / 3.8 Auto-Selection</title>
      <dc:creator>Amir mohamad</dc:creator>
      <pubDate>Wed, 23 Sep 2026 13:07:18 +0000</pubDate>
      <link>https://dev.to/fjfycfgdy/building-a-pypkg-package-runner-for-windows-with-python-314-38-auto-selection-49l1</link>
      <guid>https://dev.to/fjfycfgdy/building-a-pypkg-package-runner-for-windows-with-python-314-38-auto-selection-49l1</guid>
      <description>&lt;p&gt;Hey devs! 👋&lt;/p&gt;

&lt;p&gt;I recently built &lt;strong&gt;Python EnterPlase&lt;/strong&gt; — a small PyQt5 desktop application &lt;br&gt;
for Windows that runs &lt;code&gt;.pypkg&lt;/code&gt; package files. I want to share what it does &lt;br&gt;
and the interesting technical challenges I ran into.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;When you want to distribute a Python-based installer, you usually tell users:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"First install Python 3.x, then run these commands..."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is fine for developers, but for non-technical users, it's a pain.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;Python EnterPlase handles this automatically. You give it a &lt;code&gt;.pypkg&lt;/code&gt; file — &lt;br&gt;
a simple text file with a header and a list of shell commands — and it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Detects your Windows version&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Windows 10/11 → uses Python 3.14&lt;/li&gt;
&lt;li&gt;Windows 8.1 and below → uses Python 3.8&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Prefers an already-installed Python&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Checks &lt;code&gt;py -3.XX&lt;/code&gt; launcher&lt;/li&gt;
&lt;li&gt;Checks &lt;code&gt;C:\PythonXXX\&lt;/code&gt;, &lt;code&gt;Program Files&lt;/code&gt;, &lt;code&gt;%LOCALAPPDATA%\Programs\Python&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Checks &lt;code&gt;PATH&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Only downloads the official embeddable package if nothing is found&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Blocks dangerous commands&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Registry edits (&lt;code&gt;reg add&lt;/code&gt;, &lt;code&gt;regedit&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Disk operations (&lt;code&gt;format&lt;/code&gt;, &lt;code&gt;diskpart&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;bcdedit&lt;/code&gt;, &lt;code&gt;vssadmin&lt;/code&gt;, &lt;code&gt;net user&lt;/code&gt;, &lt;code&gt;sc create&lt;/code&gt;, and more&lt;/li&gt;
&lt;li&gt;With 3 layers of protection: preview, confirmation dialog, runtime block&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Shows everything before running&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Developer name&lt;/li&gt;
&lt;li&gt;SHA256 / SHA1 hashes (with copy button)&lt;/li&gt;
&lt;li&gt;Plain-English description of every command&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The .pypkg Format
&lt;/h2&gt;

&lt;p&gt;It's just plain text:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Commander:cmd
Developer:YourName
DS:pip,storage
SHA256:pass
SHA1:pass
pip install --upgrade pip
pip install ursina
python "C:/install.py"
=END=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Technical Challenges
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Running commands safely on Windows
&lt;/h3&gt;

&lt;p&gt;Early versions used &lt;code&gt;shell=True&lt;/code&gt; with a string command. This broke with &lt;br&gt;
quoted paths. The fix was to build the command as a &lt;strong&gt;list&lt;/strong&gt; and pass it &lt;br&gt;
directly to &lt;code&gt;subprocess.run&lt;/code&gt;:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
python
# Bad
subprocess.run(f'"{python_exe}" -m pip install ursina', shell=True)

# Good
subprocess.run([python_exe, "-m", "pip", "install", "ursina"])
2. Detecting Python without false positives
Just checking shutil.which("python") isn't enough — it might be the wrong
version. I ended up checking multiple sources in order of reliability.

3. Windows subprocess encoding
text=True alone uses the system default (cp1252). This breaks with
non-ASCII output. The fix:

python
subprocess.run(..., text=True, encoding="utf-8", errors="replace")
4. Unicode-safe GUI messages
Even the error messages can crash your app if they contain characters the
font can't render. Using errors="replace" everywhere helped.

Stack
Python 3.14 (or 3.8 on older Windows)

PyQt5 for the GUI

Nuitka for compilation (much harder to decompile than PyInstaller)

Try it out
Download: PythonEnterPlase.exe

Website: fjfycfgdy.github.io/Python-EnterPlase

It's free to use but proprietary (source not published). I'd love feedback
on the .pypkg format, the command-blocking rules, or anything else!

Have you ever built a Windows installer? How did you handle Python
version detection? Let me know in the comments!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>python</category>
      <category>pyqt5</category>
      <category>pypkg</category>
      <category>package</category>
    </item>
  </channel>
</rss>
