@jtratner "The issue in Python 3 is that you can't use string methods on bytes, but in Python 2 that's not a problem."
This is not true. Yes, it's true that you can use them, but they **won't** produce a **correct** result. Here is a simple example:
```python
>>> s = u'абвгдђежз'
>>> print s.upper()
АБВГДЂЕЖЗ
>>> print s.encode('utf8').upper()
абвгдђежз
>>> print s.encode('utf8').upper().decode('utf-8')
абвгдђежз
```
The method wont raises an error, but the result won't be correct. That's why it's important to wrap everything to be unicode. None of the `Series.str` methods would work correctly with python 2 strings if you have unicode data. Example:

```python
In [21]: s1 = pd.Series(['фоо', 'бар', 'баз'])

In [22]: s2 = pd.Series([u'фоо', u'бар', u'баз'])

In [23]: s1.str.upper()
Out[23]:
0    фоо
1    бар
2    баз
dtype: object

In [24]: s2.str.upper()
Out[24]:
0    ФОО
1    БАР
2    БАЗ
dtype: object
```
I encountered the same problem when I wrote the column detection for `read_fwf` function. Unless the strings are unicode, I cannot determine the correct widths of the columns for variable byte encodings like `utf-8`.
Yes, of course I can use the encoding and check if the thing I got is `bytes` and then decode it using the encoding, calculate the thing I need, and so on. But that is not DRY. You will have to do that all over the place in every method that does something with strings.
Instead of that, my proposal is to fix the `PythonParser.__init__` function to create a stream object (`f`) that will **always** return unicode strings, and have the logic **only** in only one place. The same thing would apply for the C parser.