Open selected file with application? Like opening a .blend file from the file explorer

Summary

The user is asking about implementing file association on Windows (specifically for a .blend-like behavior where double-clicking a file opens it in a custom Python application). This is a classic Windows Shell Integration problem. The key takeaway is that operating system file associations allow users to open files directly from the file explorer by passing the file path as a command-line argument to the executing application. For a terminal-based Python game engine, the developer needs to configure the Windows Registry to associate a specific file extension (e.g., .mygame) with the Python interpreter and their script, handling the startup arguments to capture the file path.

Root Cause

The root cause of the confusion is that Python scripts do not automatically register file associations with the OS. Unlike installed applications (like Blender) which register their capabilities during installation (writing to the Windows Registry), a standalone Python script or a loose executable lacks the necessary Shell Verbs (context menu entries) and Capability Associations. Consequently, the OS does not know to invoke the Python interpreter and pass the clicked file as an argument.

Why This Happens in Real Systems

In real systems, this requirement arises when moving from development to distribution. During development, engineers run scripts via the IDE or command line, where arguments are manually supplied. However, for end-user distribution:

  1. Installation Isolation: The OS needs explicit instructions on how to handle custom file types.
  2. Command-Line Parsing: The application must be designed to read sys.argv (or argparse) at startup. If the code expects interactive input instead of command-line arguments, it fails when launched via a double-click.
  3. Interpreter Dependency: Even if the file association is set, the OS must know whether to run python.exe, pypy.exe, or a frozen executable (like PyInstaller), requiring Proper Path Resolution in the registry.

Real-World Impact

Failing to implement this correctly leads to significant User Experience (UX) friction and adoption barriers:

  • Loss of Workflow Efficiency: Users cannot drag-and-drop assets or level files into the engine, forcing them to use clunky file dialogs or complex command-line syntax.
  • Confusion for Non-Technical Users: “Why won’t my level file open when I double-click it?” breaks the immersion of using a professional tool.
  • Reduced Tool Utility: A terminal-based engine without OS integration feels archaic and disconnected from the host operating system, reducing its appeal to indie developers who expect modern IDE-like behaviors.

Example or Code

To capture the file path on startup, you must inspect sys.argv. Here is a Python script that checks for a passed file path. Note that the actual registry modification (the OS part) is handled outside Python (via reg commands or a dedicated installer like Inno Setup), but the Python code must be ready to accept the argument.

import sys
import os

def main():
    # sys.argv[0] is the script name
    # sys.argv[1] is the first argument (the file path) if passed
    if len(sys.argv) > 1:
        file_path = sys.argv[1]
        print(f"Loading game file from: {file_path}")

        # Check if file exists and is valid
        if os.path.exists(file_path):
            # Logic to load your .mygame file
            pass
        else:
            print("Error: File does not exist.")
    else:
        # No file argument passed (e.g., launched directly)
        print("No file specified. Starting in editor mode...")

if __name__ == "__main__":
    main()

How Senior Engineers Fix It

Senior engineers approach this by combining OS-level configuration with robust application argument parsing:

  1. Implement Argument Parsing: Use argparse or sys.argv to reliably handle input arguments. The application should accept a file path as the first non-flag argument.
  2. Create an Installer or Registry Script: Do not rely on the user to edit the registry. Create a setup script (using tools like Inno Setup or NSIS) that writes the necessary registry keys.
    • Key Registry Path: HKEY_CLASSES_ROOT\.mygame (mapping extension to a file type ID).
    • Key Shell Command: HKEY_CLASSES_ROOT\MyGameEngine\shell\open\command (mapping the file type to "C:\Path\To\Python.exe" "C:\Path\To\Script.py" "%1").
  3. Handle Path Formats: Windows passes arguments with quotes if paths contain spaces. The Python script must strip quotes or use pathlib to normalize paths.
  4. Bundle the Executable: For the best UX, compile the Python script into a .exe using PyInstaller or Nuitka, and associate the .exe directly in the registry, avoiding the need for the user to have Python installed globally.

Why Juniors Miss It

Juniors often miss this aspect of tool development because:

  1. Focus on Logic, Not Distribution: They focus heavily on the game engine logic (rendering, physics) and treat file loading as an internal “Open File” dialog feature, ignoring the OS integration layer.
  2. Lack of OS Internals Knowledge: Many Python developers do not study how the Windows Registry works or how the Windows Shell executes processes, assuming the OS magically understands custom file types.
  3. Testing in IDEs: They test exclusively in VS Code or PyCharm, which handle argument passing internally. They rarely test the “Double-Click” scenario on a compiled binary or a file-unaware script launch.
  4. Fear of System Modification: Editing the registry feels dangerous. Juniors often avoid writing installers or registry scripts, preferring to keep the application “portable,” which limits functionality.