Convert Array to String Using tostring() Method in Python: Complete Array Serialization Implementation Guide

Convert array to string using tostring() method in python

Convert array to string using tostring() method in python

When I first needed to serialize numeric array data into raw bytes — for saving to a file, sending over a network socket, or interfacing with a lower-level system — I came across the array module’s tostring() method. It’s a small but genuinely useful piece of Python’s standard library, though it comes with an important caveat I had to learn about: it’s deprecated in favor of tobytes(). In this guide, I want to explain how array-to-string/bytes conversion works, why the API changed, and how I handle this correctly in modern Python.

What Is Python’s array Module?

Before diving into tostring(), it’s worth understanding the array module itself. Unlike a regular Python list, which can hold mixed types and incurs per-element object overhead, the array module provides a compact, type-restricted array — every element must be the same numeric type, stored contiguously in memory, much like an array in C.

import array

int_array = array.array('i', [1, 2, 3, 4, 5])
print(int_array)

Output:

array('i', [1, 2, 3, 4, 5])

The 'i' here is a type code indicating signed integers. Other common type codes include 'b' (signed char), 'f' (float), 'd' (double), and 'u' (Unicode character, though this was removed in Python 3.16 — I’ll touch on this later).

The tostring() Method (Deprecated)

Historically, array.array objects had a .tostring() method that converted the array’s raw memory contents into a Python bytes object:

import array

my_array = array.array('i', [1, 2, 3])
raw_bytes = my_array.tostring()
print(raw_bytes)

If I run this on a modern Python version, I actually get a DeprecationWarning (and on very recent versions, it has been removed entirely):

DeprecationWarning: tostring() is deprecated. Use tobytes() instead.

Why tostring() Was Deprecated

The name tostring() was always a bit misleading — it doesn’t return a human-readable string like "1 2 3". It returns the raw binary representation of the array’s memory contents as a bytes object. Because Python 3 draws a much stricter distinction between str (text) and bytes (binary data) compared to Python 2 — where str and bytes were essentially the same thing — the name tostring() became confusing and inconsistent with this new type model. The Python core developers introduced tobytes() as a clearer, correctly named replacement, and formally deprecated tostring() starting in Python 3.9, planning its eventual removal.

import array

my_array = array.array('i', [1, 2, 3])
raw_bytes = my_array.tobytes()
print(raw_bytes)

Output:

b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00'

Each integer here takes up 4 bytes (on most platforms, for the 'i' type code), stored in the machine’s native byte order (little-endian on most modern systems), which is exactly why I see three groups of 4 bytes for the three integers 1, 2, and 3.

Converting Bytes Back to an Array with frombytes()

The reverse operation, frombytes() (replacing the old, similarly deprecated fromstring()), lets me reconstruct an array from raw bytes:

import array

raw_bytes = b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00'

restored = array.array('i')
restored.frombytes(raw_bytes)
print(restored)

Output:

array('i', [1, 2, 3])

Getting an Actual Human-Readable String Representation

If what I actually want is a readable string — not raw binary data — I use a completely different approach: converting each element to a string and joining them, or using str()/repr() on the array directly.

import array

my_array = array.array('i', [1, 2, 3, 4, 5])

# Human-readable representation of the array object itself
print(str(my_array))

# Joining elements into a readable, comma-separated string
readable = ", ".join(str(x) for x in my_array)
print(readable)

Output:

array('i', [1, 2, 3, 4, 5])
1, 2, 3, 4, 5

This distinction — raw byte serialization versus a human-readable string — is genuinely important, and mixing them up is one of the most common points of confusion I’ve seen among people learning about the array module.

Internal Working: What tobytes()/tostring() Actually Does

Under the hood, an array.array object stores its elements in a single contiguous block of memory, exactly matching the C-level representation of that type (e.g., a C int for type code 'i', a C double for type code 'd'). Calling tobytes() essentially performs a raw memory copy of that buffer into a Python bytes object — there’s no per-element conversion loop happening at the Python level, which is why this operation is extremely fast, even for large arrays.

import array
import time

big_array = array.array('i', range(1_000_000))

start = time.time()
data = big_array.tobytes()
print(f"Time: {time.time() - start:.6f}s")
print(f"Size in bytes: {len(data)}")

Because it’s essentially copying a raw memory buffer, tobytes() runs in O(n) time relative to the array’s size, but with a very small constant factor compared to any Python-level element-by-element conversion.

Comparing array with NumPy for Serialization

For heavier numerical work, I often use NumPy instead of the standard library’s array module, and NumPy provides its own equivalent methods:

import numpy as np

numpy_array = np.array([1, 2, 3, 4, 5], dtype=np.int32)
raw_bytes = numpy_array.tobytes()
print(raw_bytes)

restored = np.frombuffer(raw_bytes, dtype=np.int32)
print(restored)

Output:

b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00'
[1 2 3 4 5]

NumPy’s tobytes() behaves conceptually the same way as array.array.tobytes() — a raw memory dump — but NumPy adds far more functionality around data types, multidimensional shapes, and numerical operations, which is why I default to it for any serious numerical or scientific work.

Real-World and Practical Use Cases

import array

data = array.array('d', [3.14, 2.71, 1.41])
with open("data.bin", "wb") as f:
    f.write(data.tobytes())

with open("data.bin", "rb") as f:
    restored = array.array('d')
    restored.frombytes(f.read())
print(restored)

Output:

array('d', [3.14, 2.71, 1.41])

Common Mistakes and Debugging Tips

  1. Confusing tostring()/tobytes() with a human-readable string conversion. These methods return raw binary data, not something meant to be printed or read directly as text.
  2. Using the deprecated tostring()/fromstring() methods in new code. These raise deprecation warnings in recent Python versions and have been removed entirely in newer releases — always use tobytes()/frombytes() instead.
  3. Mismatched type codes when restoring an array. If I serialize with type code 'i' but restore with 'f', the resulting values will be garbage, because the raw bytes are being reinterpreted as a completely different type.
import array

original = array.array('i', [1, 2, 3])
raw = original.tobytes()

wrong_restore = array.array('f')
wrong_restore.frombytes(raw)
print(wrong_restore)  # Garbage output, wrong type code used
  1. Ignoring byte order (endianness) issues when sharing binary data across different machine architectures — for true portability, I should use the struct module with explicit byte order specifiers, or NumPy’s more advanced dtype system.

Best Practices I Follow

FAQs

Q: Is tostring() still available in the latest Python versions? It was deprecated starting in Python 3.9 and has been removed in more recent versions — tobytes() is the current, correct method.

Q: Does tobytes() work the same way as tostring() did? Yes, functionally identical — it’s purely a rename for clarity, with no behavioral difference.

Q: Can I convert an array directly to a readable string of numbers? Not with tobytes()/tostring() — use something like ", ".join(str(x) for x in my_array) instead for a human-readable representation.

Q: What’s the difference between the array module and NumPy? The array module is a lightweight, standard-library-only option for simple, one-dimensional typed arrays; NumPy is a much more powerful, third-party library supporting multidimensional arrays, vectorized math, and a far richer type system.

Troubleshooting Tips

Summary

tostring() taught me an important lesson about API naming and how Python evolves over time — a method name that made sense once became a genuine source of confusion as the language’s type system matured, leading to its replacement with the far clearer tobytes(). Understanding the difference between raw binary serialization and human-readable string conversion has saved me from several subtle bugs, especially when working with files, sockets, or any system that expects exact byte-level data.

References

Exit mobile version