title: Using Python textwrap.shorten for string but with bytes width
body: <p>I'd like to shorten a string using <a href="https://docs.python.org/3/library/textwrap.html#textwrap.shorten" rel="nofollow noreferrer"><code>textwrap.shorten</code></a> or a function like it. The string can potentially have non-ASCII characters. What's special here is that <strong>the maximal <code>width</code> is for the <code>bytes</code> encoding of the string</strong>. This problem is motivated by the fact that several database column definitions and some message buses have a <code>bytes</code> based max length.</p>
  
  <p>For example:</p>
  
  <pre class="lang-py prettyprint-override"><code>&gt;&gt;&gt; import textwrap
  &gt;&gt;&gt; s = '☺ Ilsa, le méchant ☺ ☺ gardien ☺'
  
  # Available function that I tried:
  &gt;&gt;&gt; textwrap.shorten(s, width=27)
  '☺ Ilsa, le méchant ☺ [...]'
  &gt;&gt;&gt; len(_.encode())
  31  # I want ⩽27
  
  # Desired function:
  &gt;&gt;&gt; shorten_to_bytes_width(s, width=27)
  '☺ Ilsa, le méchant [...]'
  &gt;&gt;&gt; len(_.encode())
  27  # I want and get ⩽27
  </code></pre>
  
  <p>It's okay for the implementation to use a width greater than or equal to the length of the whitespace-stripped placeholder <code>[...]</code>, i.e. 5.</p>
  
  <p>The text should not be shortened any more than necessary. Some buggy implementations can use optimizations which on occasion result in excessive shortening.</p>
  
  <p><a href="https://stackoverflow.com/questions/36244817/">Using textwrap.wrap with bytes count</a> is a similar question but it's different enough from this one since it is about <code>textwrap.wrap</code>, not <code>textwrap.shorten</code>. Only the latter function uses a <code>placeholder</code> (<code>[...]</code>) which makes this question sufficiently unique.</p>
  
  <p><strong>Caution</strong>: Do not rely on any of the answers here for shortening a JSON encoded string in a fixed number of bytes. For it, substitute <code>text.encode()</code> with <code>json.dumps(text)</code>.</p>