-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
__pycache__: Initial commit (materials)
- Loading branch information
1 parent
11b2f7c
commit 4e6fc6e
Showing
18 changed files
with
162 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
public class Calculator { | ||
public static void main(String[] args) { | ||
add(3, 4); | ||
} | ||
|
||
private static int add(int a, int b) { | ||
return a + b; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
# What Is the __pycache__ Folder in Python? | ||
|
||
Source code, shell scripts, and example projects for the [What Is the `__pycache__` Folder in Python?](https://realpython.com/python-pycache/) tutorial on Real Python. | ||
|
||
## Setup | ||
|
||
You don't need to create a virtual environments because you won't be installing anything. | ||
|
||
## Cleanup Scripts | ||
|
||
To recursively remove the `__pycache__` folders on macOS and Linux: | ||
|
||
```shell | ||
$ ./pyclean.sh | ||
``` | ||
|
||
To do the same on Windows in PowerShell: | ||
|
||
```shell | ||
PS> .\pyclean.ps1 | ||
``` | ||
|
||
## X-Ray of `.pyc` Files | ||
|
||
Compile sample bytecode into timestamp-based `.pyc` files: | ||
|
||
```shell | ||
$ ./pyclean.sh | ||
$ python -m compileall --invalidation-mode timestamp example-2/ | ||
$ python xray.py example-2/__pycache__/arithmetic*.pyc | ||
{'magic_number': b'\xcb\r\r\n', | ||
'magic_int': 3531, | ||
'python_version': '3.12', | ||
'bit_field': 0, | ||
'pyc_type': <PycInvalidationMode.TIMESTAMP: 1>, | ||
'timestamp': datetime.datetime(2024, 3, 28, 17, 8, 22, tzinfo=datetime.timezone.utc), | ||
'file_size': 32} | ||
``` | ||
|
||
Compile sample bytecode into unchecked hash-based `.pyc` files: | ||
|
||
```shell | ||
$ ./pyclean.sh | ||
$ python -m compileall --invalidation-mode unchecked-hash example-2/ | ||
$ python xray.py example-2/__pycache__/arithmetic*.pyc | ||
{'magic_number': b'\xcb\r\r\n', | ||
'magic_int': 3531, | ||
'python_version': '3.12', | ||
'bit_field': 1, | ||
'pyc_type': <PycInvalidationMode.UNCHECKED_HASH: 3>, | ||
'hash_value': b'\xf3\xdd\x87j\x8d>\x0e)'} | ||
``` | ||
|
||
Compile sample bytecode into checked hash-based `.pyc` files: | ||
|
||
```shell | ||
$ ./pyclean.sh | ||
$ python -m compileall --invalidation-mode checked-hash example-2/ | ||
$ python xray.py example-2/__pycache__/arithmetic*.pyc | ||
{'magic_number': b'\xcb\r\r\n', | ||
'magic_int': 3531, | ||
'python_version': '3.12', | ||
'bit_field': 3, | ||
'pyc_type': <PycInvalidationMode.CHECKED_HASH: 2>, | ||
'hash_value': b'\xf3\xdd\x87j\x8d>\x0e)'} | ||
``` | ||
|
||
## Java Bytecode Compiler | ||
|
||
Compile the source code upfront and run the resulting class file: | ||
|
||
```shell | ||
$ javac Calculator.java | ||
$ time java Calculator | ||
``` | ||
|
||
Let the `java` command handle the compilation: | ||
|
||
```shell | ||
$ time java Calculator.java | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
import mathematics.geometry # noqa |
Empty file.
Empty file.
2 changes: 2 additions & 0 deletions
2
python-pycache/example-1/project/mathematics/arithmetic/add.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
def add(a, b): | ||
return a + b |
2 changes: 2 additions & 0 deletions
2
python-pycache/example-1/project/mathematics/arithmetic/sub.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
def sub(a, b): | ||
return a - b |
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
def add(a, b): | ||
return a + b |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from arithmetic import add | ||
|
||
add(3, 4) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
def add_function(a, b): | ||
return a + b |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
def sub_function(a, b): | ||
return a - b |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import arithmetic.add # noqa | ||
from arithmetic import add # noqa | ||
from arithmetic.add import add_function # noqa |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Get-ChildItem -Path . -Filter __pycache__ -Recurse -Directory | Remove-Item -Recurse -Force |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#!/bin/bash | ||
|
||
find . -type d -name __pycache__ -exec rm -rf {} + |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import marshal | ||
from datetime import datetime, timezone | ||
from importlib.util import MAGIC_NUMBER | ||
from pathlib import Path | ||
from pprint import pp | ||
from py_compile import PycInvalidationMode | ||
from sys import argv | ||
from types import SimpleNamespace | ||
|
||
|
||
def main(path): | ||
metadata, code = load_pyc(path) | ||
pp(vars(metadata)) | ||
if metadata.magic_number == MAGIC_NUMBER: | ||
exec(code, globals()) | ||
else: | ||
print("Bytecode incompatible with this interpreter") | ||
|
||
|
||
def load_pyc(path): | ||
with Path(path).open(mode="rb") as file: | ||
return ( | ||
parse_header(file.read(16)), | ||
marshal.loads(file.read()), | ||
) | ||
|
||
|
||
def parse_header(header): | ||
metadata = SimpleNamespace() | ||
metadata.magic_number = header[0:4] | ||
metadata.magic_int = int.from_bytes(header[0:4][:2], "little") | ||
metadata.python_version = f"3.{(metadata.magic_int - 2900) // 50}" | ||
metadata.bit_field = int.from_bytes(header[4:8], "little") | ||
metadata.pyc_type = { | ||
0: PycInvalidationMode.TIMESTAMP, | ||
1: PycInvalidationMode.UNCHECKED_HASH, | ||
3: PycInvalidationMode.CHECKED_HASH, | ||
}.get(metadata.bit_field) | ||
if metadata.pyc_type is PycInvalidationMode.TIMESTAMP: | ||
metadata.timestamp = datetime.fromtimestamp( | ||
int.from_bytes(header[8:12], "little"), | ||
timezone.utc, | ||
) | ||
metadata.file_size = int.from_bytes(header[12:16], "little") | ||
else: | ||
metadata.hash_value = header[8:16] | ||
return metadata | ||
|
||
|
||
if __name__ == "__main__": | ||
main(argv[1]) |