Numpy ndarray holding string with unknown data type
In Python 3, you shouldn't really specify the np.string_ dtype, as it is left there for backwards compatibility with Python 2. The S type you see using np.dtype is a map to the bytes_ type, a zero-terminated string buffer, which shouldn't be used.
The S just means string and the number gives the number of bytes.
In [1]: s = &quot;&quot;        # start with an empty string                                                                                                

In [2]: for i in range(5):    # make the string larger
            s += str(i) 
            a = np.array([s], dtype=np.string_) 
            print(f&quot;{a}\t{a.dtype}&quot;) 
                                                                                                                       
    [b'0']  |S1
    [b'01'] |S2
    [b'012']    |S3
    [b'0123']   |S4
    [b'01234']  |S5
    [b'012345'] |S6

For python 3 you should instead use np.unicode:
In [1]: a = np.array([&quot;hello&quot;, &quot;world&quot;], dtype=np.unicode)                                                             

In [2]: type(a)                                                                                                       
Out[2]: numpy.ndarray

In [3]: b.dtype                                                                                                       
Out[3]: dtype('&lt;U5')


&lt; means little-endian
U means a unicode string
5 relates to the number of bytes used to hold the string. If you had really long strings, that number would then increase.

Have a look at this documentation, which states:

Note on string types:
For backward compatibility with Python 2 the S and a typestrings remain zero-terminated bytes and np.string_ continues to map to np.bytes_. To use actual strings in Python 3 use U or np.unicode_.