Description: Python security, screen capture, spring physics, HiDPI and PyInstaller .exe gotchas. 7 tests from shipping 3 no-telemetry Python apps for Windows (ATLOCK, ASNIPP, APIC).
Most Python developers can write a for loop, a Flask route and a pandas one-liner.
Python experts know what happens before line 1 runs, what Python can't do, and what breaks the moment your script leaves your laptop.
I found out which one I was while building three Windows desktop apps in pure Python: ATLOCK (a security suite), ASNIPP (a screenshot and screen recorder) and APIC (an image toolkit). No ads, no analytics SDKs, no bloat. Every test below is a real bug or design decision from one of them.
Score yourself honestly. 👇
Test 1: Do you know that import order can be a security decision? (ATLOCK)
Quick: what does import ctypes have to do with security?
On Windows, a DLL imported later can be loaded from the current directory. That is how DLL planting attacks work. The fix has to run before the other imports:
import sys, ctypes
if sys.platform == "win32":
k32 = ctypes.WinDLL("kernel32", use_last_error=True)
k32.SetDllDirectoryW.argtypes = [ctypes.c_wchar_p]
k32.SetDllDirectoryW("") # drop the CWD from the DLL search path
k32.SetDefaultDllDirectories.argtypes = [ctypes.c_uint32]
k32.SetDefaultDllDirectories(0x1000) # LOAD_LIBRARY_SEARCH_DEFAULT_DIRS
# only NOW import the heavy stuff
import cryptography, argon2
Developer: puts imports in alphabetical order.
Expert: knows import order is a runtime security boundary.
This is the very first thing that runs in ATLOCK, my pure-Python security suite.
Test 2: Can your screen recorder avoid recording itself? (ASNIPP)
I built a screen recorder with a floating control bar. First recording: the bar showed up in the video. 🤦
You don't need to hide and show windows. One Win32 call, straight from Python, does it:
import ctypes
def exclude_from_capture(widget):
hwnd = int(widget.winId())
# 0x11 = WDA_EXCLUDEFROMCAPTURE (Windows 10 2004+)
ctypes.windll.user32.SetWindowDisplayAffinity(hwnd, 0x11)
The window stays visible to you and is invisible to every screen capture. That is how ASNIPP keeps its own toolbars, drawing overlay and recording border out of your videos.
Developer: crops the bar out in post.
Expert: knows ctypes gives Python the whole Windows API.
Test 3: Can your app decide what you meant, without asking? (APIC)
Good desktop software removes clicks. In APIC, my image toolkit, the rule is simple:
- Drop one image → open it in the editor.
- Drop many → open the batch converter.
def on_files(self, paths: list[str]):
if not paths:
paths, _ = QFileDialog.getOpenFileNames(
self, "Open Image(s)", "",
"Images (*.png *.jpg *.jpeg *.webp *.bmp *.tiff *.gif *.ico *.heic *.avif)")
if len(paths) == 1:
self.open_in_edit(paths[0])
elif paths:
self.open_in_convert(paths)
def dropEvent(self, event):
self.on_files([u.toLocalFile() for u in event.mimeData().urls()])
The home screen, the file dialog and drag-and-drop all go through one function. Add a new entry point and you add zero logic.
Developer: writes three code paths.
Expert: writes one funnel and lets every input flow into it. The UI is split into one module per mode (edit, convert, compress, search), and main.py only wires them together.
Test 4: Do you know the difference between "encrypted" and "encrypted correctly"? (ATLOCK)
Developer: AES.new(key, AES.MODE_ECB) and done.
Expert checklist:
- AEAD, not just encryption: AES-256-GCM authenticates every chunk.
- Slow KDF for passwords: Argon2id, not a bare SHA-256.
- Never reuse a nonce with the same key.
- Bind the header with AAD so metadata can't be swapped.
import os
from argon2.low_level import hash_secret_raw, Type
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
def seal(password: bytes, data: bytes) -> bytes:
salt = os.urandom(16)
key = hash_secret_raw(password, salt, time_cost=3, memory_cost=64 * 1024,
parallelism=4, hash_len=32, type=Type.ID)
nonce = os.urandom(12)
ct = AESGCM(key).encrypt(nonce, data, associated_data=b"v1")
return salt + nonce + ct
(Simplified. ATLOCK's real container format also does chunking, key commitment and versioning.)
Test 5: Can you make a Qt animation feel alive with 6 lines of math? (ASNIPP)
ASNIPP's capture bar is a "Dynamic Island" that bounces open. Qt's built-in easing curves felt stiff, so I wrote a damped spring and plugged it into QEasingCurve:
import math
from PyQt6.QtCore import QEasingCurve
def spring(zeta, omega):
wd = omega * math.sqrt(max(1e-6, 1 - zeta * zeta)) if zeta < 1 else 0.0
def f(t):
if t <= 0: return 0.0
if t >= 1: return 1.0
if zeta < 1: # under-damped: overshoots, then settles (the bounce)
return 1 - math.exp(-zeta * omega * t) * (math.cos(wd * t) + (zeta * omega / wd) * math.sin(wd * t))
return 1 - math.exp(-omega * t) * (1 + omega * t) # critically damped: no overshoot
return f
BOUNCY = spring(0.66, 11.0) # keep it at MODULE level (see below)
curve = QEasingCurve(QEasingCurve.Type.Linear)
curve.setCustomType(BOUNCY)
The trap: if the function is a temporary object, Python garbage-collects it while Qt still holds a pointer, and you get random crashes. Keep custom callables alive at module level. Only people who've been bitten know this one.
Test 6: Does your app look sharp on a 4K laptop with 150% scaling? (APIC)
Most Python GUI apps look blurry or oddly sized on modern displays. In Qt 6 the fix is one policy before you create the app:
from PyQt6.QtWidgets import QApplication
from PyQt6.QtCore import Qt
QApplication.setHighDpiScaleFactorRoundingPolicy(
Qt.HighDpiScaleFactorRoundingPolicy.PassThrough) # no rounding: 125%/150% stay crisp
app = QApplication(sys.argv)
app.setApplicationName("APIC")
app.setOrganizationName("Akhouri Systems")
PassThrough keeps fractional scales like 125% and 150% exact instead of snapping to 100% or 200%. Add one try/except AttributeError for older Qt builds, and your app looks native everywhere.
Developer: tests on their own monitor.
Expert: tests at 100%, 125%, 150% and 200%.
Test 7: Can you explain why Python can't truly erase a password from memory? (ATLOCK)
password = "hunter2"
password = None # is it gone? 🙂
No. Python str and bytes are immutable, and the interpreter is free to copy them. The best you can do is keep secrets in a mutable bytearray and wipe it explicitly:
buf = bytearray(b"hunter2")
# ... use it ...
for i in range(len(buf)):
buf[i] = 0
An honest Python security tool says this out loud instead of promising magic. ATLOCK's source header lists what it can't do: memory wiping is best-effort, SSD shredding can't be guaranteed, and a same-user attacker can modify the script. Python experts document their limits.
Bonus: "Why does it work in VS Code and silently do nothing as a .exe?"
All three of my apps ship as Python compiled with PyInstaller (--onefile --windowed). It cost me an evening before I learned this: in a windowed build, sys.stdout and sys.stderr are None. Any print(), logging call or library traceback can fail silently, and your app "just doesn't open."
import sys, os
for name in ("stdout", "stderr"):
if getattr(sys, name, None) is None:
setattr(sys, name, open(os.devnull, "w", encoding="utf-8"))
# and show errors somewhere a human can see them:
import ctypes
ctypes.windll.user32.MessageBoxW(None, "Startup failed: ...", "App error", 0x10)
Try the code yourself
I'm the developer behind all of this, and the three apps are the proof that it works outside tutorials. They're built by Akhouri Systems, each is pure Python packaged as an .exe in a zip, with no ads and no analytics. The only network features are the ones you trigger yourself (for example ATLOCK's optional breach check, which sends only a 5-character hash prefix).
| App | Python lesson it proves | What it is | Get it |
|---|---|---|---|
| 🔐 ATLOCK v5 | Tests 1, 4, 7 | Security suite: AES-256-GCM + Argon2id file guard, password vault, TOTP/FIDO2, anti-tamper | Direct download (zip) · Microsoft Store |
| 📸 ASNIPP v1 | Tests 2, 5 | Dynamic-Island-style screenshot, screen recorder, live drawing and editor | Direct download (zip) |
| 🖼️ APIC v1 | Tests 3, 6 | Image edit, convert, compress and search toolkit | Direct download (zip) |
If you're learning how Python behaves outside a notebook, run them and then ask what's going on under the hood. That's the fastest way I know to level up.
Your score
- 0–2 tests known: You're a Python developer. Great start, now go break things.
- 3–5: Solid. You've shipped something real.
- 6–7: You're a Python expert. Come argue with me in the comments.
Which test did you fail first? Mine was the windowed-.exe one, and I lost an entire evening to it. Tell me yours below 👇
Top comments (63)
Every time I go to your post, I see the longest comment thread in history..every time 😂
Good post though. @xulingfeng @effessdev @technogamerz @akhourianmolkumar use a discord or something lol
🤣🤣🤣
We have discord too 😁
Bro, effessdev, me, technogamerz and Puneet we 4 people literally ruin Dev.to professionalism 😆 🤣 😂
We have discord still we love to discuss everything here 😆
And thanks for your comment 👍 🙂
By the way are you a founding member of Dev.to just asking....
I don't like professionalism and i also don't like LinkedIn 🙂
yup
@francistrdev just curious to ask how you became moderator & how can a normal person apply for it_
Okay sir, we will keep your words in mind from now on.
Is he a founding member of Dev.to?
Moderator
oh 😂 💀☠️
I said him bro ☠️
Francis is very hardworking and fulfills his responsibilities as a moderator really well. He explained everything to us with so much kindness and in such a friendly way that I didn’t even feel like I was talking to a moderator. It felt like talking to a friend. He is truly an amazing moderator and a wonderful friend. I hope to meet you soon at the virtual coffee, Francis!
I want to have one more title moderator @ dev.to
@akhourianmolkumar bro since you are a Python developer can you inspect this example repository? It looks quite complicated to me just wanted to know whether you think the same...
it can be short too.
means?
.github
.gitlab
components
docs
examples
bluetooth
ble_get_started
bluedroid
nimble
NimBLE_Beacon
NimBLE_Connection
NimBLE_GATT_Server
main
include
src
CMakeLists.txt
Kconfig.projbuild
idf_component.yml
main.c
CMakeLists.txt
README.md
sdkconfig.defaults
sdkconfig.defaults.esp32
sdkconfig.defaults.esp32c3
sdkconfig.defaults.esp32c5
sdkconfig.defaults.esp32c6
sdkconfig.defaults.esp32c61
sdkconfig.defaults.esp32h2
sdkconfig.defaults.esp32s3
NimBLE_Security
ble_uart_service
bluedroid
blufi
common
esp_ble_audio
esp_ble_iso
esp_ble_mesh
esp_hid_device
esp_hid_host
hci
nimble
.build-test-rules.yml
build_system
common_components
custom_bootloader
cxx
ethernet
get-started
ieee802154
lowpower
mesh
network
openthread
peripherals
phy
protocols
security
storage
system
wifi
zigbee
README.md
tools
.codespellrc
.editorconfig
.gitignore
.gitlab-ci.yml
.gitmodules
.idf_build_apps.toml
.idf_ci.toml
.mypy.ini
.pre-commit-config.yaml
.shellcheckrc
.vale.ini
CMakeLists.txt
COMPATIBILITY.md
COMPATIBILITY_CN.md
CONTRIBUTING.md
Kconfig
LICENSE
README.md
README_CN.md
ROADMAP.md
ROADMAP_CN.md
SECURITY.md
SUPPORT_POLICY.md
SUPPORT_POLICY_CN.md
add_path.sh
conftest.py
export.bat
export.fish
export.ps1
export.sh
install.bat
install.fish
install.ps1
install.sh
pytest.ini
ruff.toml
reason.... 💀
bro do you have any APIC v2 idea please
Oh sorry I said "repository" what i meant is that specific folder in that repository which is a specific example. I was asking about that one example.
APIC v2 idea not yet :(
Bro i got an idea for ASNIPP. What if we add a scratchpad feature? We can open the scratchpad, draw something, and quickly copy it to the clipboard.
bro it is cool feature to add thanks for idea
also bro should I combine sticky notes to ASNIPP?
Hmm slightly unrelated but a feature is a feature.
Don't forget the video editing though.
yeah video editing is kindaa main stuff
sorry for being late replying my online classes are going on sorry
Oh you have online classes as well!
yeah, I will be free till 8:10pm please be online after 8:10 for guaranteed for sure please please please bruhh my class
🤣 ok 8:10...
bro before 8:10, I'm back nowwwww
Let's start thread of discussions
@puneetkumar2010 @technogamerz @effessdev
let's start 😂
wait just more 5minute bruhh my class again started to give homework
I thought it is over so I clicked leave button
Online?
yup waiting for anyone to start the thread of discussion 😂
@effessdev sleep 💤😴
yeah, "we sleep early" his meme 😂
👀
?? 😆
Bhai @effessdev jaldi so jate hai
Meri trah shorts nahi dekhte hai 🤣
youtube.com/shorts/WwHQwCoG5fk?si=...
Microsoft person using google youtube
nice 👍
and wait whatt lol didi is scrolling reels at 10:15pm, after being a IITian
Mein reels dekh rahi hu! Aab tak khana bhi nahi banaya hai . Scrolling on peak log is samay so jate hai or mujhese toh khana na banta haha.
there was a time when people said me to sleep early lol @xulingfeng and you 😂
I sleep at 1 AM.
and wake up at 4:00am
didi's brain system optimization level ☠️🔥
Sleeping early is very beneficial for your health. You should sleep for at least 9 hours because it helps you stay away from illnesses and boosts your immunity. There are many other benefits too. But if you don’t do this, you might develop a hemoglobin deficiency like I do! so...
What? You have hemoglobin deficiency? What about other IITians? 🤔
I don’t think low hemoglobin has anything to do with being an IITian. My IITian friends are just chilling, while here I am, stuck dealing with low hemoglobin. lol
By the way what is it?
I mean IITans sleep less don't they? 🤔
I’ve noticed that IIT students sleep for only six hours while preparing for their studies, but I’m not sure how many hours they sleep after college. As for me, I prefer studying at night because that’s when I like to study.
IITians is really a different league and different species for people like us 😂
🔥
@effessdev bro come onlineeeee
Ohhh brooo I forgot... sorry... 😣
Come here / discord?
here
@technogamerz @puneetkumar2010
see this:
youtube.com/shorts/_R6_KfHEdm4?si=...
😎🤣🤣
bro I've seen a shorts a really funning shorts of titled what IITian do in there free time but because it is not family friendly So I didn't shared it here 😂
☠☠ WHAT!!! WHAT DO THEY DO!!
NO WORDS??
no words left
☠️
Bro chatt with me please
If you dont want to speak with me no then!
Bro why not speaking with me discord?
The line that hit me: "Python experts know what happens before line 1 runs, what Python can't do, and what breaks the moment your script leaves your laptop."
I'm 43 days into learning Python, mostly writing tutorials and small automation scripts. Reading this list was both incredibly humbling and a massive "aha" moment.
Test 7 (the immutable string) absolutely blew my mind. I've always just set a password variable to None and assumed it was magically gone. I had no idea about bytearray and the reality of memory wiping in Python.
To answer your question about which test I failed first: I haven't built a .exe yet, but my closest equivalent was spending 3 hours debugging a script that just silently did nothing because I forgot to activate my virtual environment. No traceback, no error, just silence. I learned the hard way that a program failing quietly is way worse than one failing loudly.
This is the kind of post that separates the tutorial-followers from the actual engineers. Saving this for when I eventually build my first desktop app. Thanks for sharing!
really great to know you loved the post
this would help you to build your 1st desktop app for sure.
The windowed .exe one hit closest to home for me — an app that just doesn't open and leaves you nothing to read is the worst kind of bug, because there's no error to chase. The MessageBox fallback is the bit I'd actually copy. Quick question though: with the stdout shim in place, do tracebacks from libraries still end up anywhere useful, or is that still a blind spot?
The DLL search-path change is a useful reminder that packaging and startup order are part of the security boundary. How do you verify the packaged executable still applies the restriction before extension modules load?