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
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.) ... 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
python ctypes how to write string to given buffer - Stack Overflow
Exception ignored on calling ctypes ...Python\App\dlltest\main.py", line 59, in callback pt.value = 'python string' AttributeError: 'str' object has no attribute 'value' I dont't know how to write to the given buffer.... More on stackoverflow.com
🌐 stackoverflow.com
🌐
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
docs.python.org › 3 › c-api › buffer.html
Buffer Protocol — Python 3.14.8 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...
Find elsewhere
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.

🌐
Python
docs.python.org › 2.0 › api › bufferObjects.html
7.2.3 Buffer Objects
The string object exposes the character contents in the buffer interface's byte-oriented form. An array can also expose its contents, but it should be noted that array elements may be multi-byte values. An example user of the buffer interface is the file object's write() method. Any object that can export a series of bytes through the buffer interface can be written to a file.
🌐
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...
🌐
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 ...
🌐
Python Module of the Week
pymotw.com › 2 › StringIO
StringIO and cStringIO – Work with text buffers using file-like API - Python Module of the Week
This example uses read(), but the readline() and readlines() methods are also available. The StringIO class also provides a seek() method so it is possible to jump around in a buffer while reading, which can be useful for rewinding if you are using some sort of look-ahead parsing algorithm. $ python stringio_examples.py This goes into the buffer.
Top answer
1 of 1
1

Here's a slightly better way. Cast the pointer to (single) wchar to a pointer to an array of wchar. Then you can dereference and write the value directly to the array:

def callback(pt: POINTER(c_wchar), ptsize: c_size_t) -> None:
    pa = cast(pt,POINTER(c_wchar * ptsize))
    pa.contents.value = 'python string'

This also has the advantage that if you write more that ptsize characters to the array, Python will throw an exception. For example:

def callback(pt: POINTER(c_wchar), ptsize: c_size_t) -> None:
    s = 'a' * (ptsize + 1)  # one too big
    pa = cast(pt,POINTER(c_wchar * ptsize))
    pa.contents.value = s

This results in:

Exception ignored on calling ctypes callback function: <function callback at 0x0000020B1C7F6310>
Traceback (most recent call last):
  File "C:\test.py", line 13, in callback
    pa.contents.value = s
ValueError: string too long

Be careful of the null termination, though. Python only writes it via .value if it has room in the array. Here's a demo:

test.cpp

#include <iostream>
#include <stdio.h>

using namespace std;

typedef void(__stdcall* Mycallback2)(wchar_t* buff, size_t buffsize);

extern "C" __declspec(dllexport)
void TestMethod5(Mycallback2 callback)
{
    wchar_t* buff = new wchar_t[7];        // length 7 buffer
    swprintf_s(buff, 7, L"%s", L"123456"); // init buffer
    if (callback) callback(buff, 5);       // callback alters only 5
    wcout << L'|' << buff << L'|' << endl;
    delete[] buff;
}

test.py

from ctypes import *

dll = CDLL('./test')

MYCALLBACKTYPE = CFUNCTYPE(None, POINTER(c_wchar), c_size_t)
dll.TestMethod5.restype = None
dll.TestMethod5.argtypes = [MYCALLBACKTYPE]

def callback(pt: POINTER(c_wchar), ptsize: c_size_t) -> None:
    s = 'a' * (ptsize if demo else ptsize-1) # 4 or 5 'a' string, no explicit null
    pa = cast(pt,POINTER(c_wchar * ptsize))
    print('pt =',pa.contents.value)
    pa.contents.value = s

mycallback = MYCALLBACKTYPE(callback)
demo = 0
dll.TestMethod5(mycallback)
demo = 1
dll.TestMethod5(mycallback)

Output:

pt = 12345         # only "sees" the size reported
|aaaa|             # null was written since there was room
pt = 12345
|aaaaa6|           # null wasn't written when length 5 value written,
                   # So wcout "saw" the ending 6.
🌐
Python
python-list.python.narkive.com › JphaTxkR › string-buffer
String buffer
If n is omitted, it reads the entire buffer. To view the first n characters of the string buffer, use peek: print B.peek(5) # View first 5 characters Or cast as a string to get the entire contents: print str(B) # View entire buffer The append and read methods are O(k), where k is the number of characters appended or read.
🌐
DaniWeb
daniweb.com › programming › software-development › threads › 274804 › creating-a-buffer-class-in-python
Creating a buffer class in Python | DaniWeb
April 11, 2010 - Every call to write() appends to that string and then, while a * exists, print everything up to and including the first *, and keep the remainder. This handles partial segments that span multiple writes and also multiple * in a single chunk. class Buffer(object): def __init__(self, delimiter='*'): self._buf = '' self._delim = delimiter def write(self, text): self._buf += text d = self._delim # Print one chunk per delimiter found while True: i = self._buf.find(d) if i == -1: break chunk = self._buf[:i+1] # include the delimiter print(chunk) self._buf = self._buf[i+1:] def flush(self): if self._buf: print(self._buf) self._buf = '' # Example: # b = Buffer() # b.write('ab') # b.write('c*de*f') # prints "abc*" then "de*" # b.flush() # prints "f"
🌐
DEV Community
dev.to › pgradot › sharing-strings-between-c-and-python-through-byte-buffers-1nj0
Sharing strings between C and Python through byte buffers - DEV Community
June 17, 2020 - If you use a buffer of bytes to share strings between C (or C++) and Python, you may end up with weird results, because both languages do not represent strings the same way.
🌐
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 - 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, accessing these char buffers with a standard ...
Author: python
🌐
TutorialsPoint
tutorialspoint.com › python-program-to-clear-the-string-buffer
Python Program to Clear the String Buffer
In Python, a string buffer is a mutable sequence of characters that can be modified before writing to an output stream. Python's class from the module provides an in-memory buffer for string operations.
🌐
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 ... (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 ...