diff --git a/Documentation/release/dev/python-wrap-char.md b/Documentation/release/dev/python-wrap-char.md
new file mode 100644
index 0000000000000000000000000000000000000000..cedbd7cac3866c1367227fbd1b81d0de812ece89
--- /dev/null
+++ b/Documentation/release/dev/python-wrap-char.md
@@ -0,0 +1,9 @@
+## Change to the Python `char` wrapping
+
+If a VTK method parameter is type `char`, you can pass any python string `s`
+where `ord(s) < 256`, instead of being restricted to ASCII characters.  If a
+VTK method returns `char`, then return value is always a python `str` with
+a length of 1, with the null char being `'\x00'`.  Previously, a `char` value
+of zero would be returned as `''` (empty string), and calling `ord()` on an
+empty string raises an exception.  Now, calling `ord()` on the returned value
+will never raise an exception.
diff --git a/Wrapping/Python/Testing/Python/TestChar.py b/Wrapping/Python/Testing/Python/TestChar.py
index c95d7026ead6cc1138e7d0ca395438436ad51134..88e54fcaa53570e33d6c84ec6ba81d9b3d052b97 100644
--- a/Wrapping/Python/Testing/Python/TestChar.py
+++ b/Wrapping/Python/Testing/Python/TestChar.py
@@ -21,12 +21,12 @@ class TestChar(Testing.vtkTest):
         """Pass a unicode string and get it back.
         """
         a = vtkCharArray()
-        a.InsertNextValue('')
+        a.InsertNextValue('\0')
         a.InsertNextValue('%')
         a.InsertNextValue('\u00b5') # MICRON
         a.InsertNextValue('\u00d7') # MULTIPLICATION SIGN
         c = a.GetValue(0)
-        self.assertEqual(c, '')
+        self.assertEqual(c, '\0')
         c = a.GetValue(1)
         self.assertEqual(c, '%')
         c = a.GetValue(2)
@@ -38,12 +38,12 @@ class TestChar(Testing.vtkTest):
         """Pass a bytes object, get back a unicode object
         """
         a = vtkCharArray()
-        a.InsertNextValue(b'')
+        a.InsertNextValue(b'\0')
         a.InsertNextValue(b'%')
         a.InsertNextValue(b'\xb5') # MICRON
         a.InsertNextValue(b'\xd7') # MULTIPLICATION SIGN
         c = a.GetValue(0)
-        self.assertEqual(c, '')
+        self.assertEqual(c, '\0')
         c = a.GetValue(1)
         self.assertEqual(c, '%')
         c = a.GetValue(2)
diff --git a/Wrapping/PythonCore/vtkPythonArgs.h b/Wrapping/PythonCore/vtkPythonArgs.h
index 1aca5b9db3ea6ebc76fde6d288aa991ce4bfa3e0..c55f0e64a278447b9cfc18a9246d8bfce7e964be 100644
--- a/Wrapping/PythonCore/vtkPythonArgs.h
+++ b/Wrapping/PythonCore/vtkPythonArgs.h
@@ -891,20 +891,23 @@ inline PyObject* vtkPythonArgs::BuildValue(const std::string& a)
 
 inline PyObject* vtkPythonArgs::BuildValue(char a)
 {
-  char b[4] = { a, '\0', '\0', '\0' };
+  char b[2] = { a, '\0' };
+  Py_ssize_t n = 1;
   if ((static_cast<unsigned char>(a) & 0xc0) == 0x80)
   {
     // convert value [128,191] to equivalent utf-8 sequence
     b[0] = '\xc2';
     b[1] = a;
+    n = 2;
   }
   else if ((static_cast<unsigned char>(a) & 0xc0) == 0xc0)
   {
     // convert value [192,255] to equivalent utf-8 sequence
     b[0] = '\xc3';
     b[1] = a ^ '\x40';
+    n = 2;
   }
-  return PyUnicode_FromString(b);
+  return PyUnicode_FromStringAndSize(b, n);
 }
 
 inline PyObject* vtkPythonArgs::BuildValue(double a)