Getting Started¶
pip install pythonnative
pn --help
Create a project¶
pn init MyApp
This scaffolds:
app/with a minimalmain_page.pypythonnative.jsonproject configrequirements.txt.gitignore
A minimal app/main_page.py looks like:
import pythonnative as pn
@pn.component
def App():
count, set_count = pn.use_state(0)
return pn.Column(
pn.Text(f"Count: {count}", style={"font_size": 24}),
pn.Button(
"Tap me",
on_click=lambda: set_count(count + 1),
),
style={"spacing": 12, "padding": 16},
)
Key ideas:
@pn.componentmarks a function as a PythonNative component. The function returns an element tree describing the UI. PythonNative creates and updates native views automatically.pn.use_state(initial)creates local component state. Call the setter to update it — the UI re-renders automatically.style={...}passes visual and layout properties as a dict (or list of dicts) to any component.- Element functions like
pn.Text(...),pn.Button(...),pn.Column(...)create lightweight descriptions, not native objects.
Run on a platform¶
pn run android
# or
pn run ios
- Uses bundled templates (no network required for scaffolding)
- Copies your
app/into the generated project
If you just want to scaffold the platform project without building, use:
pn run android --prepare-only
pn run ios --prepare-only
This stages files under build/ so you can open them in Android Studio or Xcode.
Viewing logs¶
After the app launches, pn run attaches to the app's stdout/stderr so Python
print() output and tracebacks stream back into your terminal until you press
Ctrl+C:
import pythonnative as pn
@pn.component
def MainPage():
count, set_count = pn.use_state(0)
print(f"[MainPage] render count={count}")
return pn.Column(
pn.Text(f"Count: {count}"),
pn.Button("Tap me", on_click=lambda: set_count(count + 1)),
)
- On Android, logs are streamed via
adb logcatfiltered to thepython.stdout/python.stderrtags (that Chaquopy redirectsprint()to) plus the template's Kotlin tags. - On iOS Simulator, the app is launched via
xcrun simctl launch --console-pty, which forwards the Python process's standard streams to your terminal.
Pass --no-logs if you'd rather run fire-and-forget:
pn run android --no-logs
pn run ios --no-logs
Clean¶
Remove the build artifacts safely:
pn clean