Forums

Can't import submodule from included requests module

To be more specific, I am using the soundcloud module has the following line of code:

from requests.packages.urllib3.packages import six

However, it is unable to do so. Even though the "requests" module is there ("import requests" works fine), and the above code worked before (about a couple weeks ago it stopped working) and works on my local computer. Is it possible that the requests module that comes included with PA is broken?

While the requests module installed in the .local folder is complete, am I right to assume that Python will use the preinstalled one instead?

This first started occurring right around the time of the most recent upgrade. Any help is appreciated!

That looks like a pretty odd thing to be doing. As far as I know, six is a standalone Python module for scripts that are aiming to be compatible with both 2.x and 3.x, so I can't imagine why urllib3 is bundling its own copy of it instead of just listing it as a dependency. Come to that, why on earth is requests bundling urllib3 instead of listing that as a dependency? Have these people not heard of pip and virtualenv?

Anyway, poor packaging decisions aside, this looks like it might be Ubuntu messing around with packages. Perhaps they noticed the same thing I just highlighted, because it appears that the copy of requests in /usr/lib/python2.7/dist-packages/requests lacks a packages subdirectory, whereas the versions in /usr/local/lib/python2.6 and /usr/local/lib/python3.3 have it. I'm taking a guess that the one in /usr/lib is from an Ubuntu package whereas the other two are direct from PyPi.

That's just supposition on my part - I don't have access to the package management tools on PA (quite rightly!) so I can't confirm for sure. If you need a workaround for now, you could create a virtualenv on PA and install requests in it with pip, which should ensure you're using the version from PyPi. As long as you do not specify --system-site-packages when you build the virtualenv, you should be assured of using the version you install. The only problem is if you need to use any of the system packages which have binary components, which you'll be unable to install.

If you don't mind modifying the code you could instead try amending that line to simply:

import six

... and see if that works.

Ahh dug a little deeper and the requests module that comes with Ubuntu is not packaged with urllib3 (subpackaged with six), which explain why the recent change to Ubuntu for Pythonanywhere started causing this problem.

I chose to just change the soundcloud module code to import six and urllib3 directly, instead of from the requests packages. Not sure why they decided to import from the requests packages in the first place. Importing the soundcloud module works fine now, thanks for the tip Cartroo!

No problem, glad you got it working.

I can only assume that both requests and urllib3 want to avoid compatibility issues by including a known version in their distribution, but frankly I think this is pretty poor practice. It would be far better just to specify an exact version of the other package to depend on - that's why virtualenv exists.

I guess that soundcloud wants to make sure they're using the same version of them module as those other packages - or they just couldn't be bothered to add a new dependency. Either way, I think it's the wrong approach. Dependencies and version compatibility are slightly fiddly issues, but that's not a reason to resort to lazy packaging practices.