The PyInstaller official changelog lists version 6.22.3; its platform guidance says to build for the target operating system in that operating system’s environment (release notes, platform guidance). So, if you need a macOS app, build it on macOS, start with onedir, and verify its dependencies and research outputs before considering onefile. A successful build alone does not establish that results are reproducible or that the app is ready for external distribution.

This guide is for graduate and doctoral researchers handing Python analysis tools to Mac-using supervisors or collaborators; developers packaging Python research GUIs with data or native dependencies; and university support staff setting up a repeatable build and acceptance process.

Decide what “ready” means before building

Treat three outcomes as separate acceptance gates. Passing one does not automatically pass the next.

  • Runs on the build Mac: the packaged app launches and the interface responds to basic actions.
  • Reproduces the intended analysis: a known input produces results that match the expected behavior of the original Python project, with relevant settings and outputs checked.
  • Is ready for external distribution: the app meets the signing, notarization, and delivery requirements for its intended audience. Confirm those requirements against Apple’s current software distribution guidance; do not assume a local test settles them.
Set the delivery target before selecting packaging options:
  • For a lab-internal review, prioritize inspecting the bundle and documenting how the analysis was checked.
  • For a collaborator handoff, also test the installation and data workflow that the recipient will actually use.
  • For public distribution, plan a distinct release review for Apple’s current requirements. Do not promise that a working app is ready to publish until that review is complete.

Choose a route with these conditions

  • If you need a native macOS application: build on macOS. Otherwise, pause the release and arrange access to a Mac; a Windows-built artifact is not a substitute for a macOS build.
  • If dependencies or resources are not yet verified: choose onedir and inspect the output. Move to onefile only after the directory build passes the same application and analysis checks.
  • If your next user is a collaborator or public recipient: test with the intended handoff and review the applicable Apple distribution requirements. Otherwise, label the result as an internal test build rather than implying it is release-ready.

Before the first build: make a reproducible project copy

Keep the working research project intact. Create a separate build copy that you can discard or recreate without changing the original source, environment, or results. A package failure should not leave you uncertain about whether the underlying analysis project was modified.

Record the build inputs in a short note alongside that copy:

  • Python version and environment setup.
  • PyInstaller version, including the chosen 6.22.3 release when that is what you install (official changelog).
  • Project dependencies and how they are installed.
  • The target Mac architecture and the environment used for the build.
  • The build command or spec file, plus any changes made after an error.
This record is not a guarantee that another machine will behave identically. It gives you and your collaborator a way to identify what was built and what must be recreated. If you use a dependency lock or environment file, keep it with the project’s documented build instructions.

Next, inventory what the application needs beyond Python modules. Look for input examples, configuration files, templates, model or reference data, lookup tables, and other resources loaded at runtime. Mark each item as one of the following:

  • A resource the app needs to read and that can safely travel with the application.
  • An input the user chooses or supplies for a particular analysis.
  • A result, log, or configuration that the app must create or modify.
That distinction matters. A file that must change during analysis should not be treated like a read-only bundled resource. Check the project’s data-use and sharing rules before copying samples into a distributable package. Use non-sensitive test data for the initial packaging exercise.

First build: use onedir to expose collection problems

Create or activate the project’s clean macOS build environment, install the project dependencies and the intended PyInstaller release, then run the build from the project copy. Follow the official PyInstaller usage documentation for command options. For a first pass, use the default directory-style output unless your application has a specific documented reason to choose another mode.

The purpose of this build is inspection, not presentation. Check whether the output contains the application entry point, imported modules, required libraries, and data resources. A successful command means the build process completed; it does not prove that every code path, optional dependency, or runtime file lookup will work.

When a module is missing, capture the exact error and the action that triggers it. Re-run from the same project copy after making one targeted change. This makes the failure reproducible and helps you distinguish a packaging issue from a defect in the application itself.

For resources, use PyInstaller’s documented data-file and spec-file configuration. If a dependency needs special collection behavior, check whether an official or project-specific hook applies; PyInstaller documents its hook mechanism. Do not add broad, unexplained collection rules just to silence an error. Record each change and verify that it includes only what the app needs.

If you cannot reproduce a missing-module error from the clean build copy, compare the copy with the environment where the original script works. Possible causes include an undeclared dependency, a file that exists only in the original working directory, or an import that only occurs in a particular analysis path. Keep the error message, build command, and correction together so another maintainer can follow the same diagnosis.

First runtime check: launch the app and test research inputs

Do not rely only on launching the executable from a shell in the project directory. Start the packaged application from Finder as the recipient is likely to do. That can expose assumptions about the current working directory, file selection, or environment variables that were hidden during development.

Run the checks in a consistent order:

  1. Launch the app from Finder and confirm that its main window appears and responds to the intended interactions.
  2. Use the file picker to open a known, non-sensitive input sample. Confirm that the selected file is the one the analysis actually reads.
  3. Check every relative-path lookup that matters. A packaged app may run from a different working directory than the source script, so resolve bundled resources and user-selected files deliberately.
  4. Save results to the expected user-writable location. Reopen the output and confirm that it contains the expected content.
  5. Compare the packaged run with the original Python project using the same sample, settings, and relevant analysis steps. Investigate differences before treating the app as a valid research handoff.
  6. Capture the app’s logs and the exact reproduction steps for any failure. State whether the problem is a launch error, missing resource, interface issue, or analysis-result mismatch.
Keep the test evidence modest but useful: record the sample identifier, relevant settings, expected behavior, observed behavior, and where outputs were saved. Do not include private participant data or restricted research materials in a general-purpose handoff record. If results differ, rerun the original project with the same inputs before changing packaging settings. That helps you avoid “fixing” a packaging issue when the discrepancy is actually in the analysis setup, or vice versa.

Choose onedir or onefile after the directory build passes

PyInstaller documents distinct operating modes and their tradeoffs; consult its mode guidance before switching. Use the delivery need—not the appearance of the output folder—as the reason to change modes.

  • Keep onedir when maintainers need to inspect files, troubleshoot missing resources, or update the project in a controlled way. It is also the safer stage for confirming what the build collected.
  • Consider onefile when a single-file handoff solves a real transfer or installation constraint and the packaged version passes the same tests. PyInstaller’s documentation describes onefile as a different runtime arrangement, not merely a cosmetic way to compress the onedir output.
For either mode, keep the path roles clear. Bundle stable resources that the app must read. Let users select their own research inputs. Write results, logs, and editable settings to a location the user can modify. Avoid designing a workflow that expects changing data to live inside the application bundle.

After changing modes or resource rules, repeat the launch, file-selection, path, output, and comparison checks. A mode change alters the artifact you are handing off. It does not inherit the previous build’s acceptance result automatically.

Recheck the build with another project copy

Before handing the app to a collaborator, build or verify it from a separate project copy using the recorded instructions. If the app only works when launched from the developer’s working directory, depends on an unrecorded local file, or requires an undocumented manual fix, you have not yet demonstrated a repeatable build.

Use this acceptance record:

  • Build identity: PyInstaller version, Python environment, target architecture, and build instructions are recorded.
  • Runtime behavior: the app starts from Finder, opens representative inputs, and saves outputs to the intended location.
  • Research behavior: a known sample has been processed and the result compared with the original project under documented conditions.
  • Handoff: the recipient can identify the required files, input assumptions, output location, and any limitations.
  • Release status: internal testing, research reproducibility, and external distribution readiness are labeled separately.
A passing internal test is evidence for that test’s scope. It is not proof for every dataset, Mac, dependency combination, or distribution route. If the project uses native dependencies or supports multiple target environments, document which environment you actually tested rather than making an unrestricted compatibility claim.

FAQ

Can PyInstaller build a Mac app from Windows?

No. Use a macOS build environment for a macOS artifact; PyInstaller’s platform documentation explains that builds are specific to their target operating system. A Windows build may help you distribute a Windows application, but it does not replace building and testing the Mac app on macOS. If you lack access to a Mac, resolve that before committing to a Mac deliverable.

What if the packaged app cannot find research data?

First determine whether the missing file is a bundled resource, a user-selected input, or a generated output. Add required read-only resources through the documented data-file or spec configuration, then launch from Finder and test with a known sample. Keep changing outputs outside the app bundle, and verify the saved result rather than assuming a successful launch means the data workflow works.

How should I choose between onedir and onefile?

Use onedir while diagnosing dependency collection and file paths, because its output is easier to inspect. Choose onefile only when a single-file handoff addresses a real user need and you have repeated the runtime and research checks on that artifact. Rebuilding in another mode means validating the changed package again; it does not preserve the earlier mode’s acceptance result.

Does a packaged Mac app need signing and notarization?

Do not treat signing or notarization as a requirement you can infer from whether the app launches locally. The distribution route and intended audience determine what you need to verify. Consult Apple’s current developer distribution guidance before external release, and treat that review as separate from checking the app’s research behavior. Do not bypass macOS security checks to make an unreviewed app appear to work.

If your current setup is Windows or Linux only, it cannot produce the macOS build this workflow requires. Borrowed access can work, but scheduling and environment differences may make repeated builds and Finder-based checks harder to coordinate; a CI build can automate some steps but may not replace an interactive handoff test. When you need a temporary, persistent macOS environment for building and retesting, compare that route with buying hardware or continuing to borrow a Mac. MACGPU may suit a project that needs remote macOS access rather than a new purchase, but confirm the access method and project-data boundaries before moving research files. Start with the MACGPU Mac environment overview and review the available Mac options; if your lab already has reliable Mac access or needs a dedicated physical interface, use that existing setup instead.