Code and machine code
Code is text written in a programming language, so people can read and write it. Text like this is called source code. This two-line Python program uses print, which shows text on the screen: first Hello, world!, then Goodbye!
The CPU, the chip that runs programs, cannot read text. It only runs machine code: instructions stored as numbers, in a form one family of CPUs understands. These bytes are real machine code for an Intel or AMD (x86-64) chip.
So between your code and the CPU sits a translator: a program that turns source code into work the CPU can do. There are two main kinds, called compilers and interpreters.
Compiler or interpreter
A compiler translates the whole program ahead of time and saves the result as a machine-code file. C, Go and Rust usually work this way. Its job is done before the program ever runs.
Run that file and the CPU carries out its machine code directly, with no translator in between. Hello, world! and Goodbye! appear. The file only runs on the kind of CPU and system it was made for.
An interpreter works differently: it reads your code and carries it out as it goes, line by line, without saving a machine-code file. The interpreter is itself a program, already in machine code, running on the CPU.
How Python runs
Python does a bit of both. CPython, the usual Python, first compiles your whole file into bytecode: simple instructions for a virtual machine, a computer made of software. The CPU cannot run bytecode itself.
Then the CPython virtual machine, a program running on the CPU, reads the bytecode one instruction at a time and does each one. Line 1 prints Hello, world!, then line 2 prints Goodbye!
Every language has syntax: exact rules for how code is written. Drop the closing ) on line 2 and Python cannot compile the file, so nothing runs, not even line 1. It reports SyntaxError: '(' was never closed.
What happens
;; step 1/9 · source
source code text people can read and write
language Python 3
line 1 print('Hello, world!')
line 2 print('Goodbye!')
print(...) shows the text inside on the screen
quotes mark the text: 'Hello, world!'
Compiled and interpreted are two ends of a range, not two boxes. Java also compiles to bytecode, and some interpreters compile busy parts of a program to machine code while it runs (a JIT); CPython 3.13 added an experimental one. The machine-code card holds real x86-64 bytes: B8 01 00 00 00 is mov eax, 1 (Linux system call 1, write), BF 01 00 00 00 is mov edi, 1 (standard output), and 0F 05 is syscall. A whole Hello, world program needs a few more, to say where the text is and how long it is.