Bidirectional Python to Scratch 3.0 transpiler
Project description
Py2SB3
A bidirectional Python to Scratch 3.0 transpiler. Write Scratch projects in Python, or convert existing Scratch projects to Python code.
Features
- Python → Scratch: Write Python code and compile to
.sb3files - Scratch → Python: Convert existing
.sb3projects to readable Python - Round-trip: Convert Scratch → Python → Scratch while preserving all sprites and sounds
- IDE Support: Full autocomplete and type hints for all Scratch blocks
- 339 Official Sprites: Access to the complete Scratch sprite library
- Sound Library: All official Scratch sounds available
Installation
pip install py2sb3
Or install from source:
git clone https://github.com/Samuelicjones/Py2SB3.git
cd Py2SB3
pip install -e .
Quick Start
Writing Scratch in Python
from scratch import transpile_to_json, save_sb3
from scratch.dsl import * # IDE autocomplete for all blocks
class Cat:
def when_flag_clicked(self):
say("Hello!")
for i in range(10):
move(10)
turn_right(15)
wait(0.1)
def when_key_space(self):
play_sound("Meow")
# Compile to .sb3
code = open("my_game.py").read()
json_str = transpile_to_json(code)
save_sb3(json_str, "my_game.sb3")
Converting Scratch to Python
from scratch import convert_sb3_to_py
# Convert any .sb3 file to Python
convert_sb3_to_py("existing_project.sb3", "output.py")
Round-trip Conversion
from scratch import roundtrip_sb3
# Convert .sb3 → Python → .sb3 (preserves all sprites/sounds)
roundtrip_sb3("input.sb3", "output.sb3", py_path="intermediate.py")
CLI Commands
# Python to Scratch
scratch py2sb3 game.py game.sb3
# Scratch to Python
scratch sb32py project.sb3 project.py
# Round-trip (preserves assets)
scratch roundtrip input.sb3 output.sb3 --py intermediate.py
# Show project info
scratch info project.sb3
Sprite Classes
Each Python class becomes a Scratch sprite. The class name determines the sprite:
class Cat: # Uses official Cat sprite
pass
class Dog1: # Uses Dog1 sprite
pass
class MySprite: # Uses default sprite
pass
Event Handlers
Methods starting with when_ become Scratch event handlers:
| Python Method | Scratch Block |
|---|---|
when_flag_clicked() |
Green flag clicked |
when_key_space() |
When space key pressed |
when_key_up() |
When up arrow pressed |
when_key_a() |
When 'a' key pressed |
when_clicked() |
When this sprite clicked |
when_broadcast_message1() |
When I receive "message1" |
when_i_start_as_clone() |
When I start as a clone |
Supported Blocks
Motion
move(10) # Move 10 steps
turn_right(15) # Turn right 15 degrees
turn_left(15) # Turn left 15 degrees
go_to("random") # Go to random position
go_to("mouse") # Go to mouse pointer
go_to_xy(0, 0) # Go to x, y
glide_to_xy(1, 100, 100) # Glide to x, y in 1 second
point_in_direction(90) # Point in direction
point_towards("mouse") # Point towards mouse
change_x(10) # Change x by 10
set_x(0) # Set x to 0
change_y(10) # Change y by 10
set_y(0) # Set y to 0
if_on_edge_bounce() # If on edge, bounce
set_rotation_style("left-right")
x_position() # Reporter: x position
y_position() # Reporter: y position
direction() # Reporter: direction
Looks
say("Hello!") # Say
say_for_secs("Hi!", 2) # Say for 2 seconds
think("Hmm...") # Think
think_for_secs("...", 2) # Think for 2 seconds
switch_costume("costume2") # Switch costume
next_costume() # Next costume
switch_backdrop("backdrop2")
next_backdrop()
change_size(10) # Change size by 10
set_size(100) # Set size to 100%
change_effect("color", 25) # Change color effect
set_effect("ghost", 50) # Set ghost effect
clear_effects() # Clear graphic effects
show() # Show sprite
hide() # Hide sprite
go_to_layer("front") # Go to front layer
change_layer("forward", 1) # Go forward 1 layer
costume_number() # Reporter
backdrop_name() # Reporter
size() # Reporter
Sound
play_sound("Meow") # Start sound
play_sound_until_done("Pop")# Play until done
stop_all_sounds() # Stop all sounds
change_volume(-10) # Change volume
set_volume(100) # Set volume
volume() # Reporter
Control
wait(1) # Wait 1 second
for i in range(10): # Repeat 10 times
move(10)
while True: # Forever loop
move(1)
if touching("edge"): # If-then
turn_right(180)
if x_position() > 0: # If-else
move(10)
else:
move(-10)
wait_until(touching("edge"))# Wait until
while not touching("edge"): # Repeat until
move(1)
stop("all") # Stop all/this script
create_clone("myself") # Create clone
delete_this_clone() # Delete this clone
Sensing
touching("mouse") # Touching mouse pointer?
touching("edge") # Touching edge?
touching("Sprite1") # Touching sprite?
touching_color("#FF0000") # Touching color?
color_touching_color("#FF0000", "#00FF00")
distance_to("mouse") # Distance to
ask("What's your name?") # Ask and wait
answer() # Answer reporter
key_pressed("space") # Key pressed?
mouse_down() # Mouse down?
mouse_x() # Mouse x
mouse_y() # Mouse y
timer() # Timer
reset_timer() # Reset timer
property_of("x position", "Sprite1")
current("year") # Current year/month/etc
days_since_2000() # Days since 2000
username() # Username
Operators
pick_random(1, 10) # Random number
join("hello", "world") # Join strings
letter_of(1, "hello") # Letter 1 of "hello"
length_of("hello") # Length of string
contains("hello", "ell") # Contains substring?
x % y # Modulo (use mod())
round_num(3.7) # Round
math_op("abs", -5) # abs/floor/ceiling/sqrt/sin/cos/tan/etc
Variables
my_var = 0 # Create variable
my_var = 10 # Set variable
my_var += 5 # Change variable
show_variable("my_var") # Show variable
hide_variable("my_var") # Hide variable
Lists
my_list = [] # Create list
add_to_list("apple", "my_list")
delete_of_list(1, "my_list")
delete_all_of_list("my_list")
insert_at_list("banana", 1, "my_list")
replace_item_of_list(1, "my_list", "cherry")
item_of_list(1, "my_list") # Reporter
index_in_list("apple", "my_list")
length_of_list("my_list")
list_contains("my_list", "apple")
Custom Blocks
def define_jump(self, height):
"""Custom block with argument"""
change_y(height)
wait(0.5)
change_y(-height)
def when_flag_clicked(self):
self.jump(50) # Call custom block
Using Official Sprites
The transpiler includes all 339 official Scratch sprites:
from scratch import list_sprites, get_sprite_data
# List all available sprites
print(list_sprites()) # ['Abby', 'Amon', 'Andie', ...]
# Get sprite info
sprite = get_sprite_data("Cat")
print(f"Costumes: {len(sprite['costumes'])}")
print(f"Sounds: {len(sprite['sounds'])}")
Using Sounds
from scratch import list_sounds, get_library_sound_for_project
# List all sounds
print(list_sounds()) # ['A Bass', 'A Elec Bass', ...]
# Sounds are auto-detected from play_sound() calls
class Cat:
def when_flag_clicked(self):
play_sound("Meow") # Auto-included in project
Project Structure
Py2SB3/
├── src/scratch/
│ ├── __init__.py # Package exports
│ ├── transpiler.py # Core transpiler (Python ↔ Scratch)
│ ├── dsl.py # IDE stubs for autocomplete
│ ├── library.py # Sprite/sound library access
│ ├── cli.py # Command-line interface
│ └── data/
│ ├── sprites_library.json
│ └── sounds_library.json
├── tests/
│ └── test_transpiler.py
├── pyproject.toml
└── README.md
License
MIT License - see LICENSE file for details.
Contributing
Contributions welcome! Please feel free to submit a Pull Request.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file py2sb3-1.0.0.tar.gz.
File metadata
- Download URL: py2sb3-1.0.0.tar.gz
- Upload date:
- Size: 109.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9c083a7c92eeabb8181d584d1f4904d81234d2dd2ddb232d98954d6c30c78c6d
|
|
| MD5 |
2e5f890bfdc48c521cf80c45e48edd15
|
|
| BLAKE2b-256 |
2e376e22ee9adc30897e03c2b7e24fa1d2562c13c3eed772599eafb9d8c92cbc
|
File details
Details for the file py2sb3-1.0.0-py3-none-any.whl.
File metadata
- Download URL: py2sb3-1.0.0-py3-none-any.whl
- Upload date:
- Size: 109.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
adee111ae1e8d0c8478f70b26d4edb37790cbef8cb009a178c57b3462d5716ca
|
|
| MD5 |
052faefc686d1823c82fd7a0c3cb0c42
|
|
| BLAKE2b-256 |
1ba5ca7c7d02c394ab7dcba7de6238af0ef2102c1743734dbac89921378ba126
|