Skip to content

Commit

Permalink
Merge pull request #476 from realpython/python-array
Browse files Browse the repository at this point in the history
Python Array: Materials
  • Loading branch information
KateFinegan authored Dec 13, 2023
2 parents fe67c99 + 3db8403 commit 57dec9a
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 0 deletions.
39 changes: 39 additions & 0 deletions python-array/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Python's Array: Working With Numeric Data Efficiently

Sample code for the [Python's Array: Working With Numeric Data Efficiently](https://realpython.com/python-array/) tutorial on Real Python.

## audio

Read 24-bit PCM-encoded audio samples from a WAV file:

```shell
$ cd audio/
$ python read_audio.py
len(raw_bytes) = 793800
len(samples) = 264600
wave_file.getnframes() = 132300
samples.itemsize = 4
samples.itemsize * len(samples) = 1058400
```

## cruncher

Pass a Python array to a compiled C library:

```shell
$ cd cruncher/
$ gcc -shared -fPIC -O3 -o cruncher.so cruncher.c
$ python cruncher.py
array('i', [-20, 14, -7, 6, -2, 3, 0, 2, 1, 2])
```

## save_load

Persist an array in a file and load it back into Python:

```shell
$ cd save_load/
$ python save_load.py
Saved array as: 'binary.data'
array('H', [12, 42, 7, 15, 42, 38, 21])
```
Binary file added python-array/audio/PCM_24_bit_signed.wav
Binary file not shown.
23 changes: 23 additions & 0 deletions python-array/audio/read_audio.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import wave
from array import array

with wave.open("PCM_24_bit_signed.wav", mode="rb") as wave_file:
if wave_file.getsampwidth() == 3:
raw_bytes = wave_file.readframes(wave_file.getnframes())
samples = array(
"i",
(
int.from_bytes(
raw_bytes[i : i + 3],
byteorder="little",
signed=True,
)
for i in range(0, len(raw_bytes), 3)
),
)

print(f"{len(raw_bytes) = }")
print(f"{len(samples) = }")
print(f"{wave_file.getnframes() = }")
print(f"{samples.itemsize = }")
print(f"{samples.itemsize * len(samples) = }")
5 changes: 5 additions & 0 deletions python-array/cruncher/cruncher.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
void increment(int* numbers, unsigned int length) {
for (int i = 0; i < length; i++) {
numbers[i]++;
}
}
12 changes: 12 additions & 0 deletions python-array/cruncher/cruncher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from array import array
from ctypes import POINTER, c_int, c_uint, cdll

cruncher = cdll.LoadLibrary("./cruncher.so")
cruncher.increment.argtypes = (POINTER(c_int), c_uint)
cruncher.increment.restype = None

python_array = array("i", [-21, 13, -8, 5, -3, 2, -1, 1, 0, 1])
c_array = (c_int * len(python_array)).from_buffer(python_array)
cruncher.increment(c_array, len(c_array))

print(python_array)
23 changes: 23 additions & 0 deletions python-array/save_load/save_load.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from array import array
from struct import pack, unpack


def save(filename, numbers):
with open(filename, mode="wb") as file:
file.write(numbers.typecode.encode("ascii"))
file.write(pack("<I", len(numbers)))
numbers.tofile(file)


def load(filename):
with open(filename, mode="rb") as file:
typecode = file.read(1).decode("ascii")
(length,) = unpack("<I", file.read(4))
numbers = array(typecode)
numbers.fromfile(file, length)
return numbers


save("binary.data", array("H", [12, 42, 7, 15, 42, 38, 21]))
print("Saved array as: 'binary.data'")
print(load("binary.data"))

0 comments on commit 57dec9a

Please sign in to comment.