How I Fixed: CSRF Token Is Invalid

There’s an obvious fix, and a not so obvious fix to this problem – The CSRF Token Is Invalid. Please try to resubmit the form:

The CSRF Token Is Invalid. Please try to resubmit the form.
pesky.

The ‘obvious’ fix is that you may very well have forgotten to add in:

{{ form_end(yourFormNameHere) }}

To your twig form template file.

It’s easy to do, and we’ve all done it.

You may see this as:

{{ form_rest(yourFormName) }}
{{ form_end(yourFormName) }}

Also, but as of Symfony 3 at leastform_rest is now added in to form_end for free. It may have arrived earlier, but it’s late now, and I’m too tired to check.

Anyway, if that all works then perfect, and off you go.

However, the less obvious problem might be that your session directory is not writable by the web server user.

This just caught me out when setting up a new server.

I’d used Ansible to build my dev server, and then I’d also deployed a variant of my dev script to production.

However, somewhere along the way I’d boobed and created myself a var/sessions directory, and also a shared/var/sessions directory, and whilst the permissions where correct on one, they weren’t correct on the right one :/

Why might this be the case? Well, I deploy using Deployer, but I’d only just set that up to deploy to prod. During dev I simply work on the local VM – no deploy script needed. And at this stage I don’t have a staging box for  this project.

So yeah, make sure that whatever user your web server is running as – www-data in this case – also has permissions to write to whichever directory you are storing your session data in.

You can find this directory by looking in config.yml :

framework:
    # snip
    session:
        # http://symfony.com/doc/current/reference/configuration/framework.html#handler-id
        handler_id:  session.handler.native_file
        save_path:   "%kernel.root_dir%/../var/sessions/%kernel.environment%"

 

Gotcha: Upgrading To FOSRestBundle 2.0

This is not a huge issue, and likely quite easy to identify and fix. But I’m the kind of person who hits Google before engaging brain, and I didn’t find a direct answer (boo, wake up brain!).

I have, this very evening, decided to try FOSRestBundle 2.0. It’s currently still in development, so isn’t available without a little naughty composer tagging:

    "require": {
        "friendsofsymfony/rest-bundle": "^2.0@dev"
    },

A little tip there – if you use the @dev after your requested version number, you can force through development packages without globally changing your project’s minimum-stability  setting.

Anyway, being that I’ve been coding for the last 12.5 hours, I went with the lazy man’s option of copy / pasting my config from a FOSRestBundle 1.7 installation I happened to have laying around.

fos_rest:
    view:
        exception_wrapper_handler:  null
        mime_types:
            json: ['application/json', 'application/x-json']
            jpg: 'image/jpeg'
            png: 'image/png'

Firstly, I got this:

InvalidConfigurationException in ArrayNode.php line 317:
Unrecognized option "exception_wrapper_handler" under "fos_rest.view"

Which confuses me, as this seems to be the same as what’s in the configuration reference.

Anyway, simply removing that line makes the error go away.

The next error I got was this:

Warning: array_merge(): Argument #1 is not an array
500 Internal Server Error - ContextErrorException

And what this turns out to be is that the mime_types must now all be arrays:

fos_rest:
    view:
        mime_types:
            json: ['application/json', 'application/x-json']
            jpg: ['image/jpeg']
            png: ['image/png']

So there you go 🙂

Upgrading to Ansible 2.1 on OSX

I have Ansible installed on a variety of machines – primarily Ubuntu, but also for setting up the virtual machines / servers I use when recording, I also have Ansible installed on OSX.

Up until today I was running Ansible v1.9.1, but then I hit on an issue with my nginx sites not creating properly (for some reason which I did not track down), and decided the best course of action would be to upgrade all the submodules I use as the basis of my playbook infrastructure.

Just to explain this a little further – when I first started using Ansible I would git clone any interesting repository to my local machine, and then take ownership of that repo into my own project. There are pros and cons to this approach:

Pros

  • I could make changes to the repos to suit my needs
  • I knew the repo contents wouldn’t change unless I changed them
  • Everything was very explicit and obvious to new people

Cons

  • I created a lot of work for myself

Yeah, ‘busy’ work such as managing an ever expanding list of other people’s projects was not a fun thing. Instead, I switched to ‘importing’ other peoples projects by way of git’s submodules, which works a treat, but there’s a drawback:

Other people have a habit of changing things.

My mistake was to blindly update all my submodules to their latest versions:

git submodule foreach 'git fetch origin; git checkout $(git rev-parse --abbrev-ref HEAD); git reset --hard origin/$(git rev-parse --abbrev-ref HEAD); git submodule update --recursive; git clean -dfx'

This worked fine, but it turned out that some of my tracked submodules now required Ansible 2 to run.

No problem, I thought, let’s just upgrade to Ansible 2.

How naive.

The first mistake I made in this process was to try and update an OSX installation of Ansible by way of using pip install ansible –upgrade.

Yeah… not so much. Plenty of errors here:

➜  ~ sudo pip install ansible --upgrade
Password:
The directory '/Users/codereview/Library/Caches/pip/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
The directory '/Users/codereview/Library/Caches/pip' or its parent directory is not owned by the current user and caching wheels has been disabled. check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
Collecting ansible
  Downloading ansible-2.1.0.0.tar.gz (1.9MB)
    100% |████████████████████████████████| 1.9MB 576kB/s
Requirement already up-to-date: paramiko in /Library/Python/2.7/site-packages (from ansible)
Requirement already up-to-date: jinja2 in /Library/Python/2.7/site-packages (from ansible)
Requirement already up-to-date: PyYAML in /Library/Python/2.7/site-packages (from ansible)
Collecting setuptools (from ansible)
  Downloading setuptools-23.0.0-py2.py3-none-any.whl (435kB)
    100% |████████████████████████████████| 440kB 2.3MB/s
Requirement already up-to-date: pycrypto>=2.6 in /Library/Python/2.7/site-packages (from ansible)
Requirement already up-to-date: pyasn1>=0.1.7 in /Library/Python/2.7/site-packages (from paramiko->ansible)
Requirement already up-to-date: cryptography>=1.1 in /Library/Python/2.7/site-packages (from paramiko->ansible)
Requirement already up-to-date: MarkupSafe in /Library/Python/2.7/site-packages (from jinja2->ansible)
Requirement already up-to-date: cffi>=1.4.1 in /Library/Python/2.7/site-packages (from cryptography>=1.1->paramiko->ansible)
Collecting six>=1.4.1 (from cryptography>=1.1->paramiko->ansible)
  Downloading six-1.10.0-py2.py3-none-any.whl
Requirement already up-to-date: idna>=2.0 in /Library/Python/2.7/site-packages (from cryptography>=1.1->paramiko->ansible)
Requirement already up-to-date: ipaddress in /Library/Python/2.7/site-packages (from cryptography>=1.1->paramiko->ansible)
Requirement already up-to-date: enum34 in /Library/Python/2.7/site-packages (from cryptography>=1.1->paramiko->ansible)
Requirement already up-to-date: pycparser in /Library/Python/2.7/site-packages (from cffi>=1.4.1->cryptography>=1.1->paramiko->ansible)
Installing collected packages: setuptools, ansible, six
  Found existing installation: setuptools 1.1.6
    Uninstalling setuptools-1.1.6:
Exception:
Traceback (most recent call last):
  File "/Library/Python/2.7/site-packages/pip/basecommand.py", line 215, in main
    status = self.run(options, args)
  File "/Library/Python/2.7/site-packages/pip/commands/install.py", line 317, in run
    prefix=options.prefix_path,
  File "/Library/Python/2.7/site-packages/pip/req/req_set.py", line 736, in install
    requirement.uninstall(auto_confirm=True)
  File "/Library/Python/2.7/site-packages/pip/req/req_install.py", line 742, in uninstall
    paths_to_remove.remove(auto_confirm)
  File "/Library/Python/2.7/site-packages/pip/req/req_uninstall.py", line 115, in remove
    renames(path, new_path)
  File "/Library/Python/2.7/site-packages/pip/utils/__init__.py", line 267, in renames
    shutil.move(old, new)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/shutil.py", line 299, in move
    copytree(src, real_dst, symlinks=True)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/shutil.py", line 208, in copytree
    raise Error, errors
Error: [('/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/_markerlib/__init__.py', '/tmp/pip-ymaXaK-uninstall/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/_markerlib/__init__.py', "[Errno 1] Operation not permitted: '/tmp/pip-ymaXaK-uninstall/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/_markerlib/__init__.py'"), ('/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/_markerlib/__init__.pyc', '/tmp/pip-ymaXaK-uninstall/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/_markerlib/__init__.pyc', "[Errno 1] Operation not permitted: '/tmp/pip-ymaXaK-uninstall/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/_markerlib/__init__.pyc'"), ('/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/_markerlib/markers.py', '/tmp/pip-ymaXaK-uninstall/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/_markerlib/markers.py', "[Errno 1] Operation not permitted: '/tmp/pip-ymaXaK-uninstall/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/_markerlib/markers.py'"), ('/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/_markerlib/markers.pyc', '/tmp/pip-ymaXaK-uninstall/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/_markerlib/markers.pyc', "[Errno 1] Operation not permitted: '/tmp/pip-ymaXaK-uninstall/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/_markerlib/markers.pyc'"), ('/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/_markerlib', '/tmp/pip-ymaXaK-uninstall/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/_markerlib', "[Errno 1] Operation not permitted: '/tmp/pip-ymaXaK-uninstall/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/_markerlib'")]

Which is honestly fair enough – this isn’t how I’d installed Ansible originally (my poor grep skills fooled me), and this led me down some dark alleys of trying to manually fudge the upgrade of dependencies I thought were at fault – pycrypto, paramiko, and others.

The command that worked was simple:

brew install ansible
➜  ~ ansible --version
ansible 2.1.0.0

Ok, so cool, up to date with Ansible, but the playbook still wouldn’t run properly.

➜  ansible-submodule git:(master) ✗ ansible-playbook -i hosts -l symfony-3-api.dev playbook/symfony-dev.yml -k -K -s
SSH password:
SUDO password[defaults to SSH password]:
[DEPRECATION WARNING]: Instead of sudo/sudo_user, use become/become_user and make sure become_method is 'sudo' (default).
This feature will be removed in a future release.
Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.

PLAY [all] *********************************************************************

TASK [setup] *******************************************************************
No handlers could be found for logger "paramiko.transport"
fatal: [symfony-3-api.dev]: UNREACHABLE! => {"changed": false, "msg": "'EntryPoint' object has no attribute 'resolve'", "unreachable": true}
	to retry, use: --limit @playbook/symfony-dev.retry

PLAY RECAP *********************************************************************
symfony-3-api.dev          : ok=0    changed=0    unreachable=1    failed=0

Quite frustrating. I knew I could SSH onto the box, so it was likely not my server at fault.

A simpler Ansible ping command helped a little:

➜  ansible-submodule git:(master) ✗ ansible symfony-3-api.dev -i hosts -m ping -vvvv
Using /Users/Shared/Development/ansible-submodule/ansible.cfg as config file
Loaded callback minimal of type stdout, v2.0
<192.168.1.64> ESTABLISH SSH CONNECTION FOR USER: deploy
<192.168.1.64> SSH: EXEC ssh -C -vvv -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=deploy -o ConnectTimeout=10 -o ControlPath=/Users/codereview/.ansible/cp/ansible-ssh-%h-%p-%r 192.168.1.64 '/bin/sh -c '"'"'LANG=en_GB.UTF-8 LC_ALL=en_GB.UTF-8 LC_MESSAGES=en_GB.UTF-8 /usr/bin/python && sleep 0'"'"''
symfony-3-api.dev | UNREACHABLE! => {
    "changed": false,
    "msg": "SSH Error: data could not be sent to the remote host. Make sure this host can be reached over ssh",
    "unreachable": true
}

From here I found a helpful github issue which led me to this:

symfony-3-api.dev ansible_ssh_host=192.168.1.64 ansible_ssh_user=deploy ansible_connection=ssh

Note the inclusion of:

ansible_connection=ssh

But this needed a little further help to start working:

curl -O -L http://downloads.sourceforge.net/project/sshpass/sshpass/1.05/sshpass-1.05.tar.gz && tar xvzf sshpass-1.05.tar.gz
cd sshpass-1.05
./configure
make
sudo make install

After that, the ping and playbook command would run again.

➜  ansible-submodule git:(master) ✗ ansible symfony-3-api.dev -i hosts -m ping -vvvv
Using /Users/Shared/Development/ansible-submodule/ansible.cfg as config file
Loaded callback minimal of type stdout, v2.0
<192.168.1.64> ESTABLISH SSH CONNECTION FOR USER: deploy
<192.168.1.64> SSH: EXEC ssh -C -vvv -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=deploy -o ConnectTimeout=10 -o ControlPath=/Users/codereview/.ansible/cp/ansible-ssh-%h-%p-%r 192.168.1.64 '/bin/sh -c '"'"'LANG=en_GB.UTF-8 LC_ALL=en_GB.UTF-8 LC_MESSAGES=en_GB.UTF-8 /usr/bin/python && sleep 0'"'"''
symfony-3-api.dev | SUCCESS => {
    "changed": false,
    "invocation": {
        "module_args": {
            "data": null
        },
        "module_name": "ping"
    },
    "ping": "pong"
}

Jackpot.

Installing Wine 1.9.11 on Ubuntu 16.04

wine-software-that-can-lead-a-man-to-drinkIt should not have been this difficult.

But alas, it has been.

I must have spent 4 or more hours now trying to install Wine 1.9 (though any version would have been just fine after the first few hours), on Ubuntu 16.04 / Xenial.

The reason for all this Wine-ing? SQLYog. It’s by far and away the best MySQL GUI I have ever used, and nothing on Linux comes close. Wine allows me to run Windows software (almost) as though it were a native Linux app. Pretty awesome.

Now, I’ve never had any trouble installing Wine before. I’m almost positive (though it’s always worth doubting my own memory) that I’ve had Wine installed on previous Linux / Ubuntu boxes simply by using the Ubuntu Software Center. Sure, it’s an ancient version, but it does the job.

Things got so desperate that I was in the middle of installing Windows 7 into a VirtualBox VM just so I could run this one single app. And of course, whilst that was installing in the background, I managed to stumble upon a fix.

Anyway, enough background / blather, I’m sure you are only interested in how I fixed this problem.

My Solution

I followed the instruction guide from the Wine docs:

sudo dpkg --add-architecture i386 
sudo add-apt-repository ppa:wine/wine-builds
sudo apt-get update
sudo apt-get install --install-recommends winehq-devel

However this constantly threw up errors like:

Reading package lists... Done
Building dependency tree       
Reading state information... Done
Some packages could not be installed. This may mean that you have
requested an impossible situation or if you are using the unstable
distribution that some required packages have not yet been created
or been moved out of Incoming.
The following information may help to resolve the situation:

The following packages have unmet dependencies.
 winehq-devel : Depends: wine-devel (= 1.9.11~ubuntu16.04.1)

I knew there was something around the whole x64 / i386 thing going on, and along the way I learned that adding in :i386 after a package name installs the 32 bit version of the software, should you be on a 64 bit OS.

This led me to trying all manner of variations.

Then I stumbled upon this, which gave a much clearer indication of the missing dependency:

➜  ~ sudo apt-get install --install-recommends wine-devel-i386
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Some packages could not be installed. This may mean that you have
requested an impossible situation or if you are using the unstable
distribution that some required packages have not yet been created
or been moved out of Incoming.
The following information may help to resolve the situation:

The following packages have unmet dependencies.
 wine-devel-i386:i386 : Depends: libgphoto2-6:i386 (>= 2.5.9) but it is not going to be installed
                        Recommends: libgnutls-deb0-28:i386 but it is not installable or
                                    libgnutls26:i386 but it is not installable
                        Recommends: libsane:i386 but it is not going to be installed
E: Unable to correct problems, you have held broken packages.

That led me to this StackOverflow thread which got me much further, but not 100% of the way there.

The first command worked a treat:

sudo apt-get install gcc-multilib libasound2-dev:i386 libgsm1-dev:i386 libjpeg8-dev:i386 liblcms2-dev:i386 libldap2-dev:i386 libmpg123-dev:i386 libopenal-dev:i386 libv4l-dev:i386 libx11-dev:i386 libxinerama-dev:i386 libxml2-dev:i386 zlib1g-dev:i386

But the second one needed a little modification:

sudo apt-get install libcapi20-dev:i386 libcups2:i386 libdbus-1-3:i386 libfontconfig:i386 libfreetype6:i386 libglu1-mesa:i386 libgphoto2-6:i386 libncurses5:i386 libosmesa6:i386 libsane:i386 libxcomposite1:i386 libxcursor1:i386 libxi6:i386 libxrandr2:i386 libxslt1.1:i386 ocl-icd-libopencl1:i386 libgd3:i386

Fortunately, again, the output was very helpful in pointing me towards the right dependency.

With both of those installing all the bits and pieces, finally Wine installed properly:

sudo apt-get install --install-recommends winehq-devel wine-devel

Most of the frustration came from me not understanding the output clearly enough to figure out what dependency I was missing.

Some raw output which may help you debug this problem:

sudo dpkg --add-architecture i386 
sudo add-apt-repository ppa:wine/wine-builds
sudo apt-get update
sudo apt-get install --install-recommends winehq-devel
apt-mark showhold 
sudo apt-get remove wine
sudo apt-get install wine1.7
sudo apt-get install wine1.7-amd64 wine1.7-i386
sudo apt-get install --install-recommends wine-devel
sudo apt-get install --install-recommends wine-devel-i386
sudo apt-get install --install-recommends wine-devel-i386:i386
sudo apt-get install ia32-libs
sudo apt-get install wine-devel-i386
sudo apt-get install --install-recommends winehq-devel wine-devel
sudo apt-get install --install-recommends winehq-devel libasound2-plugins:i386
sudo apt-get install libcapi20-dev:i386 libcups2:i386 libdbus-1-3:i386 libfontconfig:i386 libfreetype6:i386 libglu1-mesa:i386 libgnutls26:i386 libgphoto2-2:i386 libncurses5:i386 libosmesa6:i386 libsane:i386 libxcomposite1:i386 libxcursor1:i386 libxi6:i386 libxrandr2:i386 libxslt1.1:i386 ocl-icd-libopencl1:i386
sudo apt-get install gcc-multilib libasound2-dev:i386 libgsm1-dev:i386 libjpeg8-dev:i386 liblcms2-dev:i386 libldap2-dev:i386 libmpg123-dev:i386 libopenal-dev:i386 libv4l-dev:i386 libx11-dev:i386 libxinerama-dev:i386 libxml2-dev:i386 zlib1g-dev:i386 
apt-get install libcapi20-dev:i386 libcups2:i386 libdbus-1-3:i386 libfontconfig:i386 libfreetype6:i386 libglu1-mesa:i386 libgnutls26:i386 libgphoto2-2:i386 libncurses5:i386 libosmesa6:i386 libsane:i386 libxcomposite1:i386 libxcursor1:i386 libxi6:i386 libxrandr2:i386 libxslt1.1:i386 ocl-icd-libopencl1:i386
sudo apt-get install libcapi20-dev:i386 libcups2:i386 libdbus-1-3:i386 libfontconfig:i386 libfreetype6:i386 libglu1-mesa:i386 libgnutls26:i386 libgphoto2-2:i386 libncurses5:i386 libosmesa6:i386 libsane:i386 libxcomposite1:i386 libxcursor1:i386 libxi6:i386 libxrandr2:i386 libxslt1.1:i386 ocl-icd-libopencl1:i386
sudo apt-get install --install-recommends winehq-devel wine-devel
sudo apt-get install libcapi20-dev:i386 libcups2:i386 libdbus-1-3:i386 libfontconfig:i386 libfreetype6:i386 libglu1-mesa:i386 libgphoto2-2:i386 libncurses5:i386 libosmesa6:i386 libsane:i386 libxcomposite1:i386 libxcursor1:i386 libxi6:i386 libxrandr2:i386 libxslt1.1:i386 ocl-icd-libopencl1:i386
sudo apt-get install libcapi20-dev:i386 libcups2:i386 libdbus-1-3:i386 libfontconfig:i386 libfreetype6:i386 libglu1-mesa:i386  libncurses5:i386 libosmesa6:i386 libsane:i386 libxcomposite1:i386 libxcursor1:i386 libxi6:i386 libxrandr2:i386 libxslt1.1:i386 ocl-icd-libopencl1:i386
sudo apt-get install libcapi20-dev:i386 libcups2:i386 libdbus-1-3:i386 libfontconfig:i386 libfreetype6:i386 libglu1-mesa:i386 libgphoto2-6:i386 libncurses5:i386 libosmesa6:i386 libsane:i386 libxcomposite1:i386 libxcursor1:i386 libxi6:i386 libxrandr2:i386 libxslt1.1:i386 ocl-icd-libopencl1:i386
sudo apt-get install libcapi20-dev:i386 libcups2:i386 libdbus-1-3:i386 libfontconfig:i386 libfreetype6:i386 libglu1-mesa:i386 libgphoto2-6:i386 libncurses5:i386 libosmesa6:i386 libsane:i386 libxcomposite1:i386 libxcursor1:i386 libxi6:i386 libxrandr2:i386 libxslt1.1:i386 ocl-icd-libopencl1:i386 libgd3:1386
sudo apt-get install libcapi20-dev:i386 libcups2:i386 libdbus-1-3:i386 libfontconfig:i386 libfreetype6:i386 libglu1-mesa:i386 libgphoto2-6:i386 libncurses5:i386 libosmesa6:i386 libsane:i386 libxcomposite1:i386 libxcursor1:i386 libxi6:i386 libxrandr2:i386 libxslt1.1:i386 ocl-icd-libopencl1:i386 libgd3:i386
sudo apt-get install --install-recommends winehq-devel wine-devel

wine is not an emulator

But it may make you need a drink.

Installing Scrapy 1.1 On Ubuntu 15.10

I don’t do a huge amount of Python, but when I do, it usually involves Scrapy.

As a result of not doing a lot of Python, it usually means I don’t have all the relevant gubbins (yes, that is the correct technical description) installed to make things ‘just work ™’.

On the contrary, things usually go quite wrong indeed:

Command /usr/bin/python -c "import setuptools, tokenize;__file__='/tmp/pip-build-I6du0W/lxml/setup.py';exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" install --record /tmp/pip-hwGRh6-record/install-record.txt --single-version-externally-managed --compile --user failed with error code 1 in /tmp/pip-build-I6du0W/lxml

or

Command /usr/bin/python -c "import setuptools, tokenize;__file__='/tmp/pip-build-dLB7U_/lxml/setup.py';exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" install --record /tmp/pip-KNAq8K-record/install-record.txt --single-version-externally-managed --compile --user failed with error code 1 in /tmp/pip-build-dLB7U_/lxml
Storing debug log for failure in /home/chris/.pip/pip.log

and so on.

Now, also, I am not the world’s foremost expert on Linux, and / or the package dependencies required to get Python to play nicely.

This is a polite way of saying I blindly follow the top answers on StackOverflow until whatever it is I am trying to install (e.g. Scrapy) installs without some horrendous error message. Hey, a little brutal honesty never hurt anybody.

So, to save my future sanity, here are all the things I ran today to get Scrapy 1.1 installed on Ubuntu 15.10:

➜  ~ python --version
Python 2.7.10

➜  ~ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 15.10
Release:	15.10
Codename:	wily

You will need pip installed. (sudo apt-get install python-pip worked for me.)

Then this – I am aware there are duplicates, this is a concat of about 6 different attempts. Feel free to de-dupe if you want, it makes no difference (afaik):

sudo apt-get install build-essential autoconf libtool pkg-config python-opengl python-imaging python-pyrex python-pyside.qtopengl idle-python2.7 qt4-dev-tools qt4-designer libqtgui4 libqtcore4 libqt4-xml libqt4-test libqt4-script libqt4-network libqt4-dbus python-qt4 python-qt4-gl libgle3 python-dev libxml2-dev libxslt1-dev python-dev libxml2-dev libxslt1-dev python-dev libxml2-dev libxslt-dev python-dev lib32z1-dev build-essential libssl-dev libffi-dev python-dev

And then Scrapy installed ‘first time’ using:

pip install Scrapy

Marvellous.

If you’d like to learn more Python, I’m not the best person to speak to. I would highly recommend you check out one or more of the courses listed at CourseDuck.