Usage
$ pyc [options] <file.py>pyc reads <file.py> and everything it imports, analyzes the whole program, and writes a native executable. The intermediate C is kept as <file.py>.c.
Options
| Flag | Effect |
|---|---|
-o <path>, --output <path> | Output binary path. Default: the input file name with its extension stripped. |
-x, --exec | Compile (cached in ~/.cache/pyc) and run. Arguments after the script go to the program. For #! lines. |
--strict | CPython semantics or a compile error: every type violation is fatal, and no accommodations apply. |
--permissive | The default. Named accommodations are allowed, and each one warns where it applies. |
--safe | Permissive, and also zero-initialize locals that may be read before assignment. |
--refuse-imprecise | Refuse a program whose inference left a container element or a parameter untyped. |
-b, --emit-llvm | Use the LLVM backend. |
-j, --jit | Compile with LLVM and run in-process (implies -b). |
--repl | Interactive REPL, backed by the JIT. |
-O, --optimize | Compile the generated C at -O2 (the default). |
--no-optimize | Compile the generated C at -O0, for debugging. |
-g, --debug-info | Emit debug information. |
--html | Emit an HTML view of the type-annotated program. |
-D <dir>, --system-directory <dir> | pyc's library directory. Default: $PYC_SYSTEM_DIRECTORY, else ., else the pyc executable's directory. |
-v, --verbose / -d, --debug | More output; repeat for more. --help also lists the development options. |
Modes
Static typing without boxing can't express everything CPython does. pyc's rule is that it never deviates silently.
--strict: the program has CPython's semantics, or it does not compile.--permissive(the default) additionally allows a few named accommodations. For example, a numeric slot holding bothintandfloatis widened tofloat. Each accommodation is behind a named flag, warns where it applies, and is off under--strict.
A value that genuinely holds two unrelated types is refused in every mode, with the variable and the union named. More in Strict dialect.
Module search path
Imports resolve against the current directory, then <pyc-dir>/pyc_lib/, then each directory in PYTHONPATH. The source file's own directory is not searched, so compile from the program's directory or add it to PYTHONPATH.
$ PYTHONPATH=/my/libs pyc myprogram.pySupported Python
| Classes | Inheritance, super(), class attributes, operator overloading, __str__/__repr__, __iter__/__next__, __enter__/__exit__, read-only @property, @staticmethod, @classmethod (cls(...)) |
|---|---|
| Functions | Closures, nonlocal/global, lambdas, default and mutable default arguments, *args, nested functions, local classes |
| Exceptions | try/except/else/finally, raise, user hierarchies, built-in exceptions raised by the runtime |
| Generators | yield, yield from, send(), return values |
| async / await | Compiled to coroutines and run on pyc's own event loop (no asyncio module yet) |
| Control flow | if/elif/else, for/while with else, with, match/case (all PEP 634 patterns), comprehensions, generator expressions, starred assignment |
| Built-in types | int (64-bit), float, bool, str, bytes, bytearray, list, tuple, dict, set, range, slice, None |
| Strings | f-strings, %-formatting, the str method set |
| Modules | import, from … import, packages and relative imports, all resolved at compile time |
Language extensions
pyc's builtin library (__pyc__/) is itself Python, written with a few compiler directives. They are available to library authors, and are the way to bind a C function:
| Directive | Purpose |
|---|---|
__pyc_c_call__(ret, fn, ...) | Call a C function inline |
__pyc_primitive__(sym, ...) | Invoke a compiler primitive |
__pyc_char__ | The uint8 / C char type |
__pyc_operator__ | Access C-level operators directly |
__pyc_insert_c_header__(h) | Include a C header in the generated code |
@vector("s") | Declare a class as a fixed-size value-type vector |
def sqrt(x): return __pyc_c_call__(float, "sqrt", float, x)Limitations
Out of scope by design, because they conflict with whole-program static typing:
eval,exec, dynamicimport, andgetattr/setattrwith run-time names- The full metaclass protocol, and the CPython C-extension API
- Values that need boxing: one slot holding unrelated types over time
Not yet supported, each tracked by an issue:
**kwargsand keyword-only parameters (issues/182)- Property setters and deleters (issues/007)
complex- Attribute reads through
clsin a@classmethod(issues/184) - Integers past 64 bits. Literals that don't fit are warned, and refused under
--strict. - The standard library is limited to the modules in
pyc_lib/. See Libraries.
The full list, including known wrong answers under repair, is in issues/ and ifa/issues/.