The correct answer is:

p.communicate(b"insert into egg values ('egg')")

Note the leading b, telling you that it's a string of bytes, not a string of unicode characters. Also, if you are reading this from a file:

value = open('thefile', 'rt').read()
p.communicate(value)

The change that to:

value = open('thefile', 'rb').read()
p.communicate(value)

Again, note the 'b'. Now if your value is a string you get from an API that only returns strings no matter what, then you need to encode it.

p.communicate(value.encode('latin-1'))

Latin-1, because unlike ASCII it supports all 256 bytes. But that said, having binary data in unicode is asking for trouble. It's better if you can make it binary from the start.

Answer from Lennart Regebro on Stack Overflow
🌐
Read the Docs
stackless.readthedocs.io › en › 2.7-slp › library › stringio.html
7.5. StringIO — Read and write strings as files — Stackless-Python 2.7.15 documentation
The Python Standard Library » · 7. String Services » · This module implements a file-like class, StringIO, that reads and writes a string buffer (also known as memory files). See the description of file objects for operations (section File Objects). (For standard strings, see str and unicode.) class StringIO.StringIO([buffer])¶ · When a StringIO object is created, it can be initialized to an existing string by passing the string to the constructor.
Discussions

String buffer to be filled by native side
Several places in the httpd expect that the user first requests a length and then provides a char * buffer with matching space. I would like to provide a bytearray or similar as the buffer. But MP expects a string when the parameter was a char *. My current solution looks like this: def ... More on forum.lvgl.io
🌐 forum.lvgl.io
0
0
February 4, 2021
[Python] Is there an inherent difference with a ctypes string buffer that makes it a bad idea to use to store byte data?
If you have a ctypes array called data, the direct way to access its individual elements is by just referring to data[0]. In the specific case of a c_char array, which is what create_string_buffer gives you, there's also a special data.value property which interprets the contents of the array as a C-style byte string. That is, it only reads up to the first null byte, and converts everything up to that point into a Python bytes objects. So if you don't want to treat your buffer as null-terminated, then simply don't use the value property. More on reddit.com
🌐 r/learnprogramming
3
1
November 8, 2024
How can I emulate a mutable string in Python (like StringBuffer in Java or StringBuilder in C#)? - Stack Overflow
Since Python's strings are immutable, it's inefficient to edit them repeatedly in loops. How can I use a mutable data structure to implement string operations, so as to avoid making lots of temporary More on stackoverflow.com
🌐 stackoverflow.com
[ctypes] [feature request] Create a Python string without buffer copies given a bytes pointer, size, kind
In interop scenarios, it might be useful to be able to have a Python string referencing an existing buffer without copies (e.g. if the underlying char data is stored in NumPy/PyTorch tensors, acces... More on github.com
🌐 github.com
7
May 20, 2023
🌐
w3resource
w3resource.com › python-exercises › os › python-os-exercise-16.php
Python: Write a string to a buffer and retrieve the value written, at the end discard buffer memory - w3resource
August 11, 2025 - Write a Python program to write a string to an in-memory buffer using io.StringIO, retrieve the value, and then clear the buffer.
🌐
Kodeclik
kodeclik.com › python-string-buffer
Python String Buffer
October 16, 2024 - It serves as a temporary storage space for building or modifying strings, without incurring the overhead of creating new string objects for every operation. String buffers are mutable and provide a convenient way to concatenate, modify, and manipulate strings in a memory-efficient manner. Python provides the io.StringIO module, which offers a convenient way to create a string buffer.
🌐
LVGL Forum
forum.lvgl.io › micropython
String buffer to be filled by native side - Micropython - LVGL Forum
February 4, 2021 - Several places in the httpd expect that the user first requests a length and then provides a char * buffer with matching space. I would like to provide a bytearray or similar as the buffer. But MP expects a string when the parameter was a char *. My current solution looks like this: def get_header_value(req, name): blen = req.get_hdr_value_len(name); if not blen: return None buffer = " "*blen # allocate a string as buffer incl. space for \0 req.get_hdr_value_str(name, ...
🌐
Reddit
reddit.com › r/learnprogramming › [python] is there an inherent difference with a ctypes string buffer that makes it a bad idea to use to store byte data?
r/learnprogramming on Reddit: [Python] Is there an inherent difference with a ctypes string buffer that makes it a bad idea to use to store byte data?
November 8, 2024 -

(as opposed to doing something similar natively in C)

Running into an issue where a function in a DLL expects an unsigned char * as a buffer to byte data (specifically this function reads one byte from a device and stores that byte in the passed in data buffer). So I do ctypes.create_string_buffer(size) and pass that in as the data arg to this DLL function. This works sometimes, but I just spent some time debugging why it doesn't work at times, and it seems to be because when the data being read and set has a value of 0, this causes some weird behavior where this string buffer (which I know is actually a ctypes array of c_chars, but string buffer is more concise) then treats this value as a null character, and therefore goes wacky, specifically when I try to access that byte via `data.value[0]` (this causes an index out of range error). If the byte being read and set is any other value, it seems to work fine and 0 is a valid index into this string buffer.

I don't have a full 100% grasp on what's going on here, but it *seems* like there's just something under the hood with how these string buffers are used. I think in C these issues don't exist because if you're using a buffer of chars to store byte data rather than characters, then you won't ever really parse the bytes as a string and therefore the value of 0 anywhere in the buffer won't cause weird issues.

But I guess in ctypes/python it's different? Just wanted to get other opinions here to see if my current understanding is correct or at least headed in the right direction.

Let me know if anything isn't clear!

🌐
Python Forum
python-forum.io › thread-41896.html
the quest for a mutable string (buffer)
April 4, 2024 - so often i am taking some logic from some program not in Python and need to implement it in Python. so many of these programs are constructing strings by putting string parts in over other string parts to end up with the desired result as a mutated ...
Find elsewhere
🌐
Python
docs.python.org › 3 › c-api › buffer.html
Buffer Protocol — Python 3.14.6 documentation
Certain objects available in Python wrap access to an underlying memory array or buffer. Such objects include the built-in bytes and bytearray, and some extension types like array.array. Third-part...
Top answer
1 of 11
123

Python 3

From the docs:

Concatenating immutable sequences always results in a new object. This means that building up a sequence by repeated concatenation will have a quadratic runtime cost in the total sequence length. To get a linear runtime cost, you must switch to one of the alternatives below: if concatenating str objects, you can build a list and use str.join() at the end or else write to an io.StringIO instance and retrieve its value when complete

Experiment to compare runtime of several options:

import sys
import timeit
from io import StringIO
from array import array


def test_concat():
    out_str = ''
    for _ in range(loop_count):
        out_str += 'abc'
    return out_str


def test_join_list_loop():
    str_list = []
    for _ in range(loop_count):
        str_list.append('abc')
    return ''.join(str_list)


def test_array():
    char_array = array('b')
    for _ in range(loop_count):
        char_array.frombytes(b'abc')
    return str(char_array.tostring())


def test_string_io():
    file_str = StringIO()
    for _ in range(loop_count):
        file_str.write('abc')
    return file_str.getvalue()


def test_join_list_compr():
    return ''.join(['abc' for _ in range(loop_count)])


def test_join_gen_compr():
    return ''.join('abc' for _ in range(loop_count))


loop_count = 80000

print(sys.version)

res = {}

for k, v in dict(globals()).items():
    if k.startswith('test_'):
        res[k] = timeit.timeit(v, number=10)

for k, v in sorted(res.items(), key=lambda x: x[1]):
    print('{:.5f} {}'.format(v, k))

results

3.7.5 (default, Nov  1 2019, 02:16:32) 
[Clang 11.0.0 (clang-1100.0.33.8)]
0.03738 test_join_list_compr
0.05681 test_join_gen_compr
0.09425 test_string_io
0.09636 test_join_list_loop
0.11976 test_concat
0.19267 test_array

Python 2

Efficient String Concatenation in Python is a rather old article and its main statement that the naive concatenation is far slower than joining is not valid anymore, because this part has been optimized in CPython since then. From the docs:

CPython implementation detail: If s and t are both strings, some Python implementations such as CPython can usually perform an in-place optimization for assignments of the form s = s + t or s += t. When applicable, this optimization makes quadratic run-time much less likely. This optimization is both version and implementation dependent. For performance sensitive code, it is preferable to use the str.join() method which assures consistent linear concatenation performance across versions and implementations.

I've adapted their code a bit and got the following results on my machine:

from cStringIO import StringIO
from UserString import MutableString
from array import array

import sys, timeit

def method1():
    out_str = ''
    for num in xrange(loop_count):
        out_str += `num`
    return out_str

def method2():
    out_str = MutableString()
    for num in xrange(loop_count):
        out_str += `num`
    return out_str

def method3():
    char_array = array('c')
    for num in xrange(loop_count):
        char_array.fromstring(`num`)
    return char_array.tostring()

def method4():
    str_list = []
    for num in xrange(loop_count):
        str_list.append(`num`)
    out_str = ''.join(str_list)
    return out_str

def method5():
    file_str = StringIO()
    for num in xrange(loop_count):
        file_str.write(`num`)
    out_str = file_str.getvalue()
    return out_str

def method6():
    out_str = ''.join([`num` for num in xrange(loop_count)])
    return out_str

def method7():
    out_str = ''.join(`num` for num in xrange(loop_count))
    return out_str


loop_count = 80000

print sys.version

print 'method1=', timeit.timeit(method1, number=10)
print 'method2=', timeit.timeit(method2, number=10)
print 'method3=', timeit.timeit(method3, number=10)
print 'method4=', timeit.timeit(method4, number=10)
print 'method5=', timeit.timeit(method5, number=10)
print 'method6=', timeit.timeit(method6, number=10)
print 'method7=', timeit.timeit(method7, number=10)

Results:

2.7.1 (r271:86832, Jul 31 2011, 19:30:53) 
[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)]
method1= 0.171155929565
method2= 16.7158739567
method3= 0.420584917068
method4= 0.231794118881
method5= 0.323612928391
method6= 0.120429992676
method7= 0.145267963409

Conclusions:

  • join still wins over concat, but marginally
  • list comprehensions are faster than loops (when building a list)
  • joining generators is slower than joining lists
  • other methods are of no use (unless you're doing something special)
2 of 11
15

Depends on what you want to do. If you want a mutable sequence, the builtin list type is your friend, and going from str to list and back is as simple as:

 mystring = "abcdef"
 mylist = list(mystring)
 mystring = "".join(mylist)

If you want to build a large string using a for loop, the pythonic way is usually to build a list of strings then join them together with the proper separator (linebreak or whatever).

Else you can also use some text template system, or a parser or whatever specialized tool is the most appropriate for the job.

🌐
docs.python.org
docs.python.org › 3 › library › stringio.html
io — Core tools for working with streams
Binary I/O (also called buffered I/O) expects bytes-like objects and produces bytes objects. No encoding, decoding, or newline translation is performed. This category of streams can be used for all kinds of non-text data, and also when manual control over the handling of text data is desired. The easiest way to create a binary stream is with open() with 'b' in the mode string...
🌐
DaniWeb
daniweb.com › programming › software-development › threads › 274804 › creating-a-buffer-class-in-python
Creating a buffer class in Python | DaniWeb
April 11, 2010 - — jcao219 18 Jump to Post ... class StringBuffer: def write(self, input): s = input t = s if '*' in input: input += t # input = input.'do not print anything that comes after the *, but retain it) print input else: s += t #just keep concatenating until we have a * call def flush(self): print input.#'print anything after the *' del input ... class StringBuffer(object): def __init__(self): #OnInit self._buffered = "" def write(self, text): self._buffered += text if "*" in self._buffered: iasterisk = self._buffered.rfind("*") + 1 print self._buffered[0:iasterisk] self._buffered = self._buffered[
🌐
TutorialsPoint
tutorialspoint.com › python-program-to-clear-the-string-buffer
Python Program to Clear the String Buffer
The reset method resets the buffer to its initial state and clears all the characters from the buffer. We can use the buffer.reset() method to clear the string buffer and set the buffer to its initial state. In the below example, we will create a string buffer using the StringIO module and then write a sequence of characters i.e string to a buffer.
🌐
Python Reference
python-reference.readthedocs.io › en › latest › docs › functions › buffer.html
buffer — Python Reference (The Right Way) 0.1 documentation
The object argument must be an object that supports the buffer call interface (such as string, unicode, bytearray, mmap.mmap or array.array). ... Optional. Buffer slice offset; if omitted the buffer object will be a slice from the beginning of object. ... Optional. Length of the slice; if omitted the slice will extend to the end of object.
🌐
GitHub
github.com › python › cpython › issues › 104689
[ctypes] [feature request] Create a Python string without buffer copies given a bytes pointer, size, kind · Issue #104689 · python/cpython
May 20, 2023 - if the underlying char data is stored in NumPy/PyTorch tensors, accessing these char buffers with a standard Python interface is helpful for debugging and sometimes for perf). I think it currently might be possible with ctypes and making use of existing PyUnicode/PyASCIIobject object layout and resetting the size/data fields to my own values. I agree that usefulness over copying the byte buffer is not very prominent, but still might be useful in some specific scenarios: e.g. by mmap'ing a giant string from a disk file and being able to examine it in an easy way
Author   python
🌐
Delft Stack
delftstack.com › home › howto › python › buffer interface in python
Buffer in Python | Delft Stack
March 11, 2025 - In this tutorial, we will delve into the concept of the buffer interface in Python, exploring how it works and the functions you can use to implement it. Whether you are a beginner or an experienced developer, understanding the buffer interface can help you write more efficient code and optimize your applications.
Top answer
1 of 3
4

In Python, you don't have to care about memory management. You don't need to reserve "buffers", just assign the variables you want, and use them.

If you assign too many (for your RAM), you might run into MemoryErrors, indicating you don't have enough memory.

You could use a Queue as some kind of buffer, though, e.g.

import random
from Queue import Queue, Full

q = Queue(100)

for i in range(10):
    #fill queue
    while True:
        try:
            q.put_nowait(random.randint(1,10))
        except Full:
            break
    #take some values from queue
    print "Round", i,
    number_of_values_to_get = random.randint(0,20)
    print "getting %i values." % number_of_values_to_get
    for j in range(number_of_values_to_get):
        value = q.get()
        print "  got value", value

I create a Queue of size 100, i.e., a maximum of 100 entries can be stored in it. If you try to put on a full queue, it will raise the corresponding exception, so you better catch it. (This is only True if you use put_nowait or put with a timeout, just look at the docs for more details.)

In this example, for ten rounds, I fill a "buffer" (queue) of 100 random integers. Then, I pick between 0 and 20 values from this buffer and print them.

I hope this helps. The main use-case for queues is multithreaded program execution, they are thread-safe. So maybe you'll want to fill the queue from one thread and read it from another. If you don't want multithreading, collections.deque might be a faster alternative, but they are not thread-safe.

2 of 3
1

use a queue / list and make indices fall off on first-in first-out basis whenever the queue / list size is sufficiently large

🌐
Reddit
reddit.com › r/learnpython › how do i convert a string to bytes?
r/learnpython on Reddit: How do I convert a string to bytes?
August 8, 2023 -

Suppose I something like

s = "GW\x25\001"

How do I convert that string to bytes, interpreting the backslashes as escapes? In other words, the resulting byte array should be of length 4.

UPDATE: Hmmm, I was taking the string from sys.argv[1], which seems to complicate things and not make it turn out as expected. So I'm still not sure what the answer is.

🌐
Python
docs.python.org › 3.11 › c-api › buffer.html
Buffer Protocol — Python 3.11.15 documentation
Certain objects available in Python wrap access to an underlying memory array or buffer. Such objects include the built-in bytes and bytearray, and some extension types like array.array. Third-part...