Search code examples
pythonpython-3.xweasyprint

Need help understanding bytes-like object vs str in Python 3.5


I'm having trouble getting a library working on Windows with Python 3.5 or 3.4 (see this issue [1]). I thought I'd take a closer look at why it's failing.

I believe the problem boils down to some code that looks like this, the results of which I don't understand:

import urllib.request
import sys
a = 'c:\Python35\Lib\site-packages\weasyprint\css\html5_ua.css'
b = a.encode(sys.getfilesystemencoding())  ## 'mbcs' on windows
c = urllib.request.pathname2url(b)

Running this in the interpreter gives:

TypeError: a bytes-like object is required, not 'str'

However, change the last line to:

c = urllib.request.pathname2url(a)

and it works fine. type(a) is < class 'str' >

I'm confused because it tells me it wants a bytes-like object, but it only works when I pass it a < class 'str' > object. Hopefully this is something easily explained and I'm just missing it.

Stack trace using command-line interpreter:

Python 3.5.1 (v3.5.1:37a07cee5969, Dec  6 2015, 01:38:48) [MSC v.1900 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import urllib.request
>>> import sys
>>> a = 'c:\Python35\Lib\site-packages\weasyprint\css\html5_ua.css'
>>> b = a.encode(sys.getfilesystemencoding())  ## 'mbcs' on windows
>>> c = urllib.request.pathname2url(b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python35\lib\nturl2path.py", line 48, in pathname2url
    if not ':' in p:
TypeError: a bytes-like object is required, not 'str'
>>>

[1] WeasyPrint usage with Python 3.x on Windows


Solution

  • urllib.request.pathname2url takes a string, not a bytes-like object. The error message you're getting comes from the bytes object, when urllib tries to use it like a string and the bytes object wants to be passed other bytes-likes.