Skip to main content

python-to-binary

py2bin turns Python into machine code using nothing but the Python standard library. No Cython, Nuitka, mypyc, Rust, C, C++, PyInstaller, PPCI, bootloader, assembler, linker or SDK - and no gcc or clang at any point. The only thing a build needs is an interpreter.

pip install python-to-binary
py2bin compile-capi app.py --target darwin-arm64 -o app

Source, issues and the full documentation: https://github.com/yu314-coder/python_to_binary

Platforms

What compile-capi - the tier that turns your program into machine code that drives CPython - can target today.

x86-64 arm64
macOS ✅ works ✅ works · 📦 ships a real app
Windows ✅ works · 📦 ships a real app ✅ works
Linux ✅ works ✅ works · 📦 ships a real app

📦 marks a target a complete third-party GUI application has been built for and run on real hardware rather than only a corpus: ManimStudio - 10,100 lines, pywebview, Pillow, manim - as a Windows x86-64 .exe, a macOS arm64 app and a Linux arm64 executable, all three working. iOS is not a py2bin target; that app's iPad/iPhone build is a separate native Swift port embedding CPython for arm64-iphoneos, and is not this compiler's work.

An iPad can build all three of them, though. py2bin has no compiler, assembler or linker behind it - it writes the machine code and the Mach-O, PE and ELF itself - so a cross-build is arithmetic and file writing, which a sandbox allows. Run inside the embedded Python of the iPad app:

built on iPadOS artifact carried off by opened on the target
Windows x86-64 .exe USB ✅ opens and runs
macOS arm64 .app, and a .dmg of it USB ✅ opens and runs
Linux arm64 ELF executable USB ✅ opens and runs

Nothing on that path needs subprocess, ctypes, fork or exec - every target still compiles with all of them removed from the interpreter, which is a test. The iPad is a build machine and nothing else: an App Store app cannot exec an arbitrary binary, so there is no such thing as a py2bin artifact that runs on the tablet that made it.

Each working target is held to the same standard: an 889-program corpus is compiled for it and every program's output and exit code compared against CPython's. macOS agrees on 878 and differs on 7; a 100-program slice run through Wine agrees on 93 and differs on 5. The differences are the same on every platform and are inherent rather than open - CPython's "Did you mean" needs a Python frame to suggest from, and the repr of a compiled function really is a builtin function's.

The native tier (py2bin compile, no CPython at all) targets all six.

New in 0.8.7

A long function no longer needs a bigger stack frame than a short one. Every intermediate the C lowering needed took a stack slot and never gave it back, so a function's frame grew with its length rather than with how much of it was live at once. About eighteen hundred statements in a single def reached the 512 KB budget and the build was refused outright - which generated code walks into without doing anything unusual. Slots taken for a statement's temporaries are handed back when it finishes, and the frame is now built from the high-water mark rather than from what happens to be outstanding at the end. Forty thousand statements in one function compile and answer correctly, where 1,900 was refused before.

Two things had to be got right and both have tests. A local, or the scratch area the float formatter allocates the first time a program prints a double, outlives the statement that created it - reclaiming those handed a later statement slots something still held, which did not print wrong numbers but exhausted the heap. And reclaiming is per statement rather than per expression, which is what keeps a loop's condition alive across its own body.

A decorator written without the @ was skipped. greet = trace(greet) kept calling the undecorated body: a module-level def became a direct C call keyed on the name alone, so a later rebinding of that name was never consulted. A def now earns the direct call only when it is the one thing binding the name at module scope.

Three more of the same shape, all asking does the module bind this name where the question is is it bound yet: print(y) above y = 5 handed the program a raw NULL instead of raising NameError, the same for a class used above its class, and a call above its own def answered rather than raising. The replacement rule is positional, so a function may still call one written below it and recursion keeps the direct call. Nine tests pin it, five of which fail against 0.8.6; no measurable speed cost.

New in 0.8.6

0.8.5 could not build anything through py2bin make or build.py. An append option nobody passed is None rather than an empty list, and the change that stopped --exclude fetching what it excluded read it without a default - so every --auto-fetch build without --exclude stopped with a TypeError. Fixed, and every append option is now checked for a default by a test.

The three questions offer six machines rather than five (linux-x86_64 was missing), Linux gains a one-file shape, and all sixteen target-and-shape combinations are driven through build.py end to end in testing.

A helper naming a module constant, or calling another helper, is now written out at its call site: bump(v) over weigh(v) collapses to v * SCALE + 1, 0.67x to 1.26x against the interpreter.

New in 0.8.5

A correctness sweep. Each of these produced a wrong result rather than an error, which is the worst way for a compiler to be wrong; all are now pinned by tests.

  • A name the program bound was ignored - its own len, str, print or super lost to the builtin, and a module-level function called through a rebound name calling the wrong one.
  • A bundle could not find the packages it carried, on Linux: the program asked CPython where it was, and CPython - handed no argument vector - answered with its own installation.
  • sys.argv held one entry this compiler had put there, so a command-line tool could not read what it was asked to do. It is taken from the operating system now.
  • len(5) answered -1 instead of raising, leaving the TypeError set.
  • A two-piece f-string ran __add__; an f-string joins.
  • A wheel's executable bit was dropped, so a package shipping a helper program could not start it.

Two that destroyed things: --clean removed whatever was at the output path, directory and contents; --include removed its own source when the output was in the same directory. Both are refused now.

New: --onefile for a macOS .app and for targets with no bundle; --exclude reaching the fetch rather than downloading what it excluded; a syntax error reported with file, line and column instead of a traceback.

Faster too - seven of sixteen measured operations now beat CPython, where two did. See the table below.

What it guarantees

Names the program binds are the program's. Integers do not stop at 64 bits. Floats stay floats and -0.0 stays distinct. Evaluation order is Python's, and a __len__ or __getitem__ runs exactly once. Exceptions - class, message, __cause__, traceback, what except matches - are the interpreter's.

Where it knowingly differs: a generator expression is built eagerly; builtins.len and builtins.str replaced at run time are not observed (print is); attribute access is slower than the interpreter's, because matching it means reading ob_type out of an object this treats as opaque - which is what lets one binary run against a CPython it was not built against.

The paths through it

Three ways to turn a program into an artifact. They trade the same three things against each other, and which one you want depends on which you care about.

compile compile-capi freeze
speed on a 30M-iteration loop 0.05 s 0.44 s 0.74 s
artifact 32 KB 50 KB 24 MB
needs Python on the machine? no yes, or bundle it no, it carries one
how much Python works a small subset most of it: 878 of an 889-program corpus1 everything
third-party packages none any the interpreter can import carried inside
what actually runs your logic machine code machine code CPython, interpreting

compile is the fastest and the smallest. Python AST → py2bin IR → optimizer → handwritten x86-64/ARM64 → ELF, PE or Mach-O. There is no interpreter in the artifact and none on the machine: 14× faster than CPython on that loop, in 32 KB that runs on a bare system. You pay for it in what it will accept - integers, floats, strings, control flow, your own functions - and it will not import a package at all.

freeze is the most complete. It ships your program beside an interpreter that runs it, so NumPy, Torch and a GUI toolkit all work exactly as they do now. Nothing is translated, so nothing is faster; the artifact is the largest of the three because an interpreter and every dependency are inside it.

compile-capi is the middle, and the one under active work. It translates ordinary Python into C that drives the CPython C API, then compiles that C with py2bin's own C compiler - the tier Nuitka occupies, with Nuitka's dependency on clang removed. Almost the whole language goes through, and anything the linked interpreter can import still works, so a real application with pywebview and Pillow compiles. Integer loops beat CPython because their locals are held in registers, and so is float arithmetic; attribute and method access are slower, because each is a real C-API call where the interpreter has a per-site cache that reads the object's internals directly. The per-feature table is below.

The loop above is deliberately unkind to compile-capi: its accumulator is compared against a parameter, which the register analysis cannot claim, so the fast path is off. On a loop it can claim, the same tier is 1.17× faster than CPython; a float loop, once the worst row at 0.32×, is 1.06×; and a call to a small helper is 2.10×, because the call stops existing and the loop around it becomes machine arithmetic.

Using it

pip install python-to-binary
command what it does
py2bin make three questions, then a bundle - see below
py2bin compile-capi Python → C driving the CPython C API → machine code
py2bin compile Python → machine code, no CPython anywhere
py2bin compile-c py2bin's own C compiler, on your C
py2bin freeze ship the program beside an interpreter
py2bin targets list the targets this build knows

Bundling a real application into a macOS .app that carries its own interpreter and packages:

py2bin compile-capi app.py --target darwin-arm64 \
  --app --name "My App" --icon icon.icns \
  --embed-python --site ../Resources/site-packages \
  --bundle-site /path/to/venv/lib/python3.14/site-packages \
  --prune-unused --zip-stdlib --include web \
  -o dist/MyApp.app --clean

--include PATH carries a file or directory beside the program - a web/ folder, templates, anything it opens at runtime rather than imports. make finds those on its own; this is how to name one it did not.

How it works

Nothing wraps a toolchain; each stage is a module you can read.

capi_emit.py        Python AST  ->  C that calls the CPython C API
capi_ints.py          which locals may live in a machine register
c_preprocessor.py   #include, macros, conditionals
c_frontend.py       C  ->  py2bin IR
native/ir.py        the IR itself
native/optimizer.py constant folding, dead code, write merging
native/arm64.py     IR  ->  ARM64 instructions
native/x86_64.py    IR  ->  x86-64, System V and Microsoft x64
native/formats/     Mach-O, PE32+, ELF
freezer.py          bundling: interpreter, packages, pruning, archives
cabi.py             the vetted CPython entry points

So compile-capi is five stages, all of them in this package: capi_emitc_preprocessorc_frontendnative.x86_64/native.arm64native.formats.macho/pe.

There is no import ctypes anywhere on that path, which a test asserts by compiling in a fresh interpreter and listing what got loaded. ctypes is standard library and would pass an imports-only-stdlib check, but it pulls in subprocess - and there are Pythons where a subprocess is not something a program may have.

Three questions, and nothing to type

py2bin make

It asks which file is the program, which machine it is for, and what shape it should take. Everything else is found or downloaded rather than typed - the other .py files beside it, the libraries it imports, an interpreter for the target, web/ and assets/ if they are there, and an icon if one is.

the shape offered first what comes out
macOS a compressed .dmg holding the app
Windows one .exe that unpacks itself
Linux one executable

Two other ways in ship in the source distribution: build.py runs a clone with nothing installed, and get-py2bin.py fetches py2bin for a machine with neither - falling back to curl or wget where Python's own networking is kept away from the interpreter.

Bundling for Windows

The executable, the interpreter and the packages share one directory, and one command assembles it:

py2bin compile-capi app.py --target windows-x86_64 --crash-log \
  --runtime /path/to/embeddable-cpython \
  --bundle-site /path/to/site-packages \
  -o dist/win/MyApp.exe

Neither needs a path on this machine: --auto-fetch downloads the interpreter for the target, and --fetch-package NAME downloads and unpacks a project's wheel. Both are checked against a published hash and cached.

--bundle-site copies packages into Lib\site-packages and names it on the interpreter's path, which has to happen together: the embeddable CPython ships a pythonXY._pth naming exactly two places, and once it exists sys.path is those two and nothing else. Packages are invisible until the path file names them, and the program reports ModuleNotFoundError for a directory plainly on disk - silently, if it is windowed.

A wheel must also match the interpreter's ABI, not only its version: cp314 and cp314t differ by a character, the second is for the free-threaded build, and only one loads.

macOS bundles, signing and disk images

--app writes a .app; --embed-python makes it carry its own interpreter, so it runs on a Mac with no Python installed. The bundle is signed and sealed as the last step of the build, once everything is in place, and codesign --verify --deep --strict exits 0 on the result.

The signature is ad-hoc - no Apple Developer ID, no notarisation, since either needs a paid account and Apple's own tooling. That only matters to Gatekeeper, which inspects apps carrying a quarantine flag: copied from a USB stick there is none, downloaded through a browser there is, and then the app needs one trip through System Settings → Privacy & Security → Open Anyway.

--dmg writes a mountable disk image beside the bundle. No hdiutil is involved, because nothing in this library may reach for a subprocess; the filesystem is written byte by byte as ISO 9660 with Joliet, which macOS mounts with files executable - what an .app needs in order to launch.

py2bin compile-capi app.py --app --dmg -o dist/MyApp.app

What compile-capi supports

Every row is checked by compiling it, running it, running the same source under CPython, and requiring identical stdout and exit status.

feature
int, float, str, bytes, bool, None
unbounded integers (2 ** 200 exact)
f-strings, format specs, !r/!s/!a
list, tuple, dict, set, slicing, subscripts
comprehensions and generator expressions
if / while / for / else, break, continue
chained comparison, ternary, and / or
functions: defaults, *args, **kwargs
lambdas and closures
classes, __init__, methods, inheritance, super()
dunder methods (__repr__, __eq__, …)
decorators
try / except / finally, with
import, from … import, relative imports
global / nonlocal, tuple unpacking
the whole program: every .py beside the entry is compiled in
__name__, __file__, inspect.signature on compiled functions
walrus (:=)
raise … from …
starred unpacking (a, *b, c = …)
match: values, |, captures, sequences, guards
match: mapping and class patterns, __match_args__
generators: yield, send, yield from, return value
async def / await, driven by a real event loop
match: starred sequence patterns ([a, *rest])
yield inside try / except
yield/await inside try / finally
yield/await inside with, including suppression
a finally that itself yields; break out of one
async for / async with
nonlocal, as a cell a closure can rebind
a closure over a name still moving, with Python's late binding
unpacking into nested tuples, attributes, subscripts
raise SomeError - a class rather than an instance

A generator cannot be compiled the way the rest is - a C function has one entry and its locals die with its frame, so it cannot stop in the middle of itself. It is turned inside out instead: the body is cut into blocks at each yield, the blocks are numbered, and the function becomes a class whose __next__ dispatches on which block to run next, with the locals as attributes because they have to outlive a return. The class is then compiled by the machinery that already compiles classes, so there is no new C and nothing interpreted at run time.

That covers yield as a statement or as a value, send, yield from, straight-line code, if/else, while, for, break, continue and a bare return. next(g) is g.send(None) here as it is in the protocol, and yield from is written as the loop it is before the body is cut - which forwards iteration but not a send into the sub-generator, so a yield from whose value is used is refused rather than quietly answering None.

A try/except around a yield works, and the way it works is worth saying, because "the handler has to survive the suspension" sounds like it needs something the cut cannot give. It does not: an exception can only be raised while a block is running, so each block of the guarded region carries the handler and it is re-established on every entry rather than having to persist across one.

await is the same machine with a second name on it. Awaiting an object with __await__ means delegating to the iterator it answers with, and a state machine is one - so an async def compiles to the same class, plus __await__ returning itself, and await x is PEP 380's expansion of yield from x.__await__(). A real event loop then drives it through send exactly as it drives a coroutine: asyncio.run, asyncio.sleep and asyncio.gather all work on compiled coroutines.

A finally around a yield works, and so do with, async for and async with - see How finally and with are handled above for how, and for the two shapes that are still refused.

A refusal is a file:line:col error, never a silent approximation. On an 889-program corpus, 878 programs produce byte-identical output to CPython; the 7 that differ do so inherently (CPython's "Did you mean" needs a Python frame, "v" is "v" depends on interning) and 4 are refused outright.

How fast each one is

Measured on an Apple M4 (10 cores - 4 performance, 6 efficiency - 24 GB, macOS 27.0, arm64) against CPython 3.14.3, python.org framework build - the interpreter these binaries actually bind, which is not the same as whichever python3 is first on PATH and does not perform alike.

300,000 iterations per row, nine fresh processes each, median taken, timing only the hot loop so neither column pays for start-up. Higher is better. The harness and cases are in benchmarks/ in the repository.

feature py2bin CPython
direct function call 2.8 ms 6.9 ms 2.50× faster
integer arithmetic 5.0 ms 8.1 ms 1.61× faster
while loop 4.4 ms 6.5 ms 1.46× faster
comparisons 3.9 ms 4.5 ms 1.15× faster
float arithmetic 5.1 ms 5.5 ms 1.08× faster
exception raise/catch 19.0 ms 19.2 ms 1.01× faster
comprehension 5.8 ms 5.6 ms 0.96×
dict store 8.1 ms 7.7 ms 0.96×
list append 5.4 ms 5.1 ms 0.95×
subscript 7.9 ms 5.9 ms 0.75×
f-string 23.5 ms 17.1 ms 0.73×
string concatenation 6.5 ms 4.5 ms 0.69×
and / or 9.0 ms 5.9 ms 0.66×
attribute read 6.9 ms 4.0 ms 0.57×
closure call 12.6 ms 6.9 ms 0.55×
instantiation 37.2 ms 15.7 ms 0.42×
method call 15.8 ms 6.4 ms 0.41×

Ratios are computed from the unrounded timings, so dividing the millisecond figures as shown gives a slightly different number in the last decimal.

One recorded run, the one in benchmarks/last-run.json in the repository. Repeat it and the figures move by a few per cent either way - which rows beat the interpreter, and by roughly how much, does not.

Where those numbers came from

Nine of the seventeen rows sit at 0.80× or better and six beat the interpreter outright. Most did not a short while ago.

row before the fix after it what it was
direct function call 0.81× 2.10× the call hid the arithmetic from the register analysis
exception raise/catch 0.49× 1.06× every raise classified its argument through a Python-level type()
float arithmetic 0.32× 1.06× floats were never held in registers at all
attribute read 0.51× 0.82× the name was built and hashed at every access
string concatenation 0.14× 0.80× literal text was joined at run time, every time
list append 0.28× 0.72× a lookup, a bound method and a discarded None per call
instantiation 0.09× 0.51× __init__ was reached through a Python-level wrapper
method call 0.05× 0.40× so was every other method

The largest wins were not optimisations but mistakes being removed - a wrapper written in Python on the method path, a float analysis that did not exist, a string rebuilt on every iteration of a loop. And they all have one shape: something stops happening. Adding a cheap test in order to skip expensive work inside the interpreter was tried five times and measured flat or slower every time, because the extra call through the import table cost more than it saved.

Arithmetic loops win because a local the analysis picks out is held in a machine register - a long long for an integer, a double for a float - with an overflow check that falls back to unbounded arithmetic when an integer leaves the word. That is what CPython's specialising interpreter does, and doing anything less was what made this tier slower than not compiling at all.

Everything else loses, by a factor that tracks how many C-API calls the operation costs. Each one is a real call with the reference-count discipline around it, where the interpreter's specialised bytecode does the same work inline.

Method calls used to be far worse than that pattern predicted - 21×, where everything else paid 2-4×. Every compiled method was wrapped in functools.partialmethod to make it bind, and that wrapper's __get__ is written in Python, so each obj.method ran interpreted code before the call could start. CPython's own instancemethod does the same binding in C, and both are now within the general pattern.

Raising a class

raise ValueError names a class and raise ValueError("x") an instance, and the two want different things from the C API - asking type() for the class of a class answers type, the metaclass. The plainest raise a program can write therefore ended in SystemError: exception <class 'type'> is not a BaseException subclass, in compiled code of every kind. Fixed.

How finally and with are handled

A generator becomes a class with __next__, not a generator: never closed, never finalised by the collector, so the only ways out of a protected region are the ones the rewriter can see. The cleanup is not a real finally: - a yield returns from __next__, so one would fire on every suspension. It is attached to the raising path as a handler that runs it and re-raises, while the ordinary path jumps to a block holding the same cleanup. with expands into the try it stands for and takes that path, with __exit__ looked up once on the type and suppression honoured.

async for and async with take the same route, each written out as what it stands for. A return here is signalled by raising StopIteration, so the cleanup's handler had to learn to tell the frame leaving from a real failure - otherwise __aexit__ is handed a StopIteration where CPython passes None.

A finally that itself yields works too: the cleanup is a block and a block may suspend, reached the same way from both paths, with whatever was raised waiting in a name until it is done. A break or continue leaving the region runs a copy of the cleanup first, which is what it would have reached had it left the ordinary way.

One file, both ways

On macOS an application is a directory - Finder runs Contents/MacOS/<name> and Gatekeeper reads Contents/Info.plist beside it. Nuitka says so in its own help: --mode=app is "onefile except on macOS where it creates an app bundle". What stays open is how much is inside the bundle, and --onefile folds the payload into the bundle's own executable.

files to hand over first start later starts
py2bin --app 495 66.0 MB 84 ms 84 ms
py2bin --app --onefile 3 23.0 MB 4.3 s 134 ms
py2bin --app --dmg 1 image 21.8 MB 84 ms 84 ms
Nuitka --mode=app 255 73.5 MB 79 ms 79 ms

The packed bundle unpacks once into a content-addressed cache and runs from there. A self-extracting single executable is what py2bin builds on Windows and Linux, and Nuitka where it can - on macOS it declines that shape once pyobjc is in the graph, which is any pywebview program.

Measured against Nuitka

manim_app: 10,100 lines, pywebview + Pillow + pyobjc, built both ways on the same machine.

The two bundle tables were taken at 0.8.5 and have not been re-taken. They need the application's own virtualenv staged into wheels, which is not a build this repository can run on its own. Every other figure here was re-measured for 0.8.7.

py2bin Nuitka
whole .app 66.0 MB 73.5 MB
main binary 8.9 MB 28.9 MB
native extensions carried 8.7 MB 8.7 MB
start with the app's imports 84.4 ms 78.6 ms
compile time 20.1 s 88.3 s

Whole-process time - start-up included - median of 5, seconds, on the same Apple M4 against Nuitka 4.1.3 --standalone:

workload py2bin CPython Nuitka
integer arithmetic 0.061 0.099 0.094
while loop 0.055 0.084 0.062
nested loops 0.021 0.025 0.027
function calls 0.020 0.038 0.036
string building 0.022 0.024 0.026

Two of those rows finish in under thirty milliseconds, so start-up is a large share of them - a real difference between the three rather than a distortion. The margins that are about generated code are the loops and the calls. This compiler's weaknesses do not show up in a five-loop benchmark at all; for those read the grid above, where method call and instantiation sit at 0.41×. Put a hot loop at module level instead of in a function and the loop advantage goes away, because module-scope names are not narrowed into registers.

What a build costs

Run time is what a user waits for; build memory is what decides whether the build runs at all. py2bin never starts a C toolchain. Peak resident set of the whole build process tree, sampled every 25 ms. Nuitka keeps a ccache and a module cache and py2bin keeps none, so both answers are given - py2bin's column is the same in each.

Cold - a first build, or CI without a warm cache:

what is being built py2bin Nuitka
a small program (~10 lines) 38-42 MB 0.1-0.2 s 564-719 MB 17-18 s
200 functions 186 MB 2.0 s 678 MB 18.7 s
1,000 functions 601 MB 7.5 s 833 MB 23.7 s
3,000 functions 1,514 MB 22.0 s 1,740 MB 36.3 s

Warm - Nuitka's cache in place, which is what a second build gets:

what is being built py2bin Nuitka
a small program 40-42 MB 0.1-0.2 s 294-303 MB 3.6-4.4 s
200 functions 186 MB 2.0 s 417 MB 4.7 s
1,000 functions 601 MB 7.3 s 762 MB 7.9 s
3,000 functions 1,568 MB 21.0 s 1,517 MB 17.1 s

A small build costs a seventh of a warm Nuitka's and a fifteenth of a cold one, which is the whole reason an iPad can run one. The advantage narrows with program size: nothing here streams, so the curve is steeper than clang's.

Startup, print("x"), median of 13 runs, same M4:

startup on disk
py2bin compile-capi 10.1 ms 49 KB
CPython 13.8 ms -
Nuitka --standalone 15.4 ms 17.2 MB

Loops beat both because a local the analysis picks out is held in a register rather than on the heap, with the overflow check that falls back to unbounded arithmetic when it leaves the word. Calls still lose: an argument is boxed at the call and unboxed inside, where the interpreter's specialised call pays neither.

Licence

MIT. Full documentation, source and issues: https://github.com/yu314-coder/python_to_binary

  1. That sweep was last run before the optimisation work described further down, and its harness was scratch rather than committed, so the figure is reported as measured rather than as currently verified. What is checked on every change is the 1529-test suite and a differential set that demands byte-identical output to CPython.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

python_to_binary-0.8.7.tar.gz (39.7 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

python_to_binary-0.8.7-py3-none-any.whl (579.2 kB view details)

Uploaded Python 3

File details

Details for the file python_to_binary-0.8.7.tar.gz.

File metadata

  • Download URL: python_to_binary-0.8.7.tar.gz
  • Upload date:
  • Size: 39.7 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.3

File hashes

Hashes for python_to_binary-0.8.7.tar.gz
Algorithm Hash digest
SHA256 2891bd31e2809a02908de576fcee0a5086f4dcc56190c950a88d3dbe39495e9f
MD5 d7f393a256c234c86e3372fb5248027c
BLAKE2b-256 ca68614351e41ee080aa4ef7c0e71e89f652606b4cbe9f39e2387e1c13e27194

See more details on using hashes here.

File details

Details for the file python_to_binary-0.8.7-py3-none-any.whl.

File metadata

File hashes

Hashes for python_to_binary-0.8.7-py3-none-any.whl
Algorithm Hash digest
SHA256 a0f47a87567e1e064b631039679383b10a50fa15e4774b2661eb58326f807ce9
MD5 445a5d08b01ea884bf8532dde35799bf
BLAKE2b-256 44c295e41aa7ee9fb585d7ae12c21a67eac3dc57d317866a0e7fbd036e6bc06d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page