Creating a Portable Python (local install) for Linux

16,840

Solution 1

I just tested this and it works great.

Get the copy of python you want to install and untar it and cd to the untarred folder first.

Also get a copy of setuptools and untar that.

/opt/portapy used below is of course just the name I came up with for this post, it could be any path and the full path should be tarred up and the same path should be used on any systems you put this on due to absolute path linking.

mkdir /opt/portapy
cd <python source dir>
./configure --prefix=/opt/portapy && make && make install
cd <setuptools source dir>
/opt/portapy/bin/python ./setup.py install

Make the virtual env folder inside the portapy folder.

mkdir /opt/portapy/virtenv
/opt/portapy/bin/virtualenv /opt/portapy/virtenv
cd /opt/portapy/virtenv
source bin/activate

Done. You are ready to install all of your libraries here and have the option of creating multiple virtual envs this way.

You can then tar up the whole /opt/portapy folder and transport it to any Linux system of the same arch, within reason I suspect.

I compiled 2.7.5 ond centOS 5.8 64bit and moved the folder to a Cent6.9 system and it runs perfectly.

Solution 2

I don't know how this is even possible. If it were, they woudn't need to distribute binary packages of python for different platforms. You can't simply distribute python that will run on any platform. It has to be built from source for that arch. Virtualenv will expect you to tell it which system python to use (using links).

This pretty much goes for almost any binary package that links against system libs. Again, if it were possible, we wouldn't need any platform specific binary distributions.

You can, however, achieve part of what you want. That is, running python on another machine that doesn't have python installed as long as its the same arch. This is the same concept behind freezing, or py2exe/py2app/pyinstaller. An interpreter is bundled into a standalone environment. So the app can run on any similar platform.

Edit

I just realized that while your question speaks about "system" agnostically, your title contains the reference "linux". There are different flavors of linux, so in order for it to work you would have to build it fat for multiple archs and also completely contain the standalone links. You might try building a package with pyinstaller and using that to include in your project.

You can try just building python from source, in your virtualenv:

$ ./configure --prefix=/path/to/virtualenv && make && make install

If you still have problems with the links to libs, you can also investigate building it statically

Solution 3

I'm not sure that working solely in Python is the way to go here. You might have better luck with Puppet of Chef, which are configuration tools that can be used to create a local environment. There is plenty of code out there to install virtualenv and python on just about any Linux plus OSX (probably not Windows though).

Your workflow would be to install chef or Puppet (your choice), run a script to install the Python you want, then enter a virtualenv and pip install any packages you might need.

Sorry this isn't as easy as virtualenv alone, but it is much more robust.

Solution 4

I faced the same problem, so I created PortableVirtualenv. Your Question is just the definition of it.

I use it as a base for commercial multiplatform app I develop. (But PortableVirtualenv is public domain - use it freely.)

If needed, you can pip-install any package and zip the whole directory to distribute also packages you need.

Solution 5

Well, since I rarely accept "can't be done", there is a way to do it. Warning: it isn't pretty and you should probably look into a different scenario.

What you will need to to is determine a standard location for this top level directory. Second, using that directory as your root you will need to compile Python on each Linux distribution you want to run this on. For this you would use something like "/usr/local/myappname/platform/" to configure and compile Python to live in. In each case substitute "platform" with the name of the platform such as "/usr/local/rhel/". If memory serves the configure option you are looking for here is --prefix.

Once you have each distribution compiled you will need a script to determine which one to use and either set environment variables or have it create symlinks to the appropriate "installation" of python. I would then use virtualenv and bootstrap in that tree to keep the "in-use" python libraries even more specific.

I can't think of a common Linux distribution that doesn't have Python by default. As such you could use setup.py and/or basic python scripts to script this out since you should be able to rely in Python being present - even if its ye olde version as in RHEL installs. Personally I find the above method overly complicated but it would meet your stated requirements with the allowance for a final script. Of course, you could use shar (SHell ARchive) to tar all of this into a runnable shell script to do the installation and avoid the need for secondary scripts. If you gzip the resulting shel archive then you can decompress it on target systems and execute it to set everything up.

All that said, I would not recommend this. I would recommend determining the minimum Python version you can run on and ensuring that is installed by the distribution whenever possible and if needs be pulling down from a repo and installing. Then, use virtualenv and bootstrap with a requirements.txt to install necessary python libraries and apps into the virutalenv. For that see this documentation

Share:
16,840

Related videos on Youtube

Nick
Author by

Nick

Updated on September 16, 2022

Comments

  • Nick
    Nick over 1 year

    I'm looking to create the following:

    A portable version of python that can be run on any system (with any previous version of python or no python installed) and have it pre-configured with various python packages (ie, django, lxml, pysqlite, etc)

    The closest I've found to the above is virtualenv, but this only goes so far.

    If I package up a nice virtualenv for python on one machine, it contains sym links to a lot of the libraries it needs. I can take those sym links and convert them to their actual files, but if I try to move this entire directory to another machine, I get seg fault after seg fault.

    To launch python on a different machine, I'm using:

    LD_LIBRARY_PATH=lib/ ./bin/python
    

    and in lib/ I have all of the shared libraries I copied from the original machine. The problem here is these shared libraries might rely on other shared libraries that I'm not including, so executing this on other linux distros does not work. Probably due to it falling back on older shared libaries installed on the system that do not work with what I copied over.

    Anyone have an idea on how to get this working? Is this even possible?

    EDIT:

    To clarify, the desired outcome is to create a tar.gz of a python binary and associated packages (django, lxml, pysqlite, etc) that can be extracted and run on any linux based system, ie (ubuntu 8.04, redhat 5, suse 11, etc), all 32bit distros, where the locally installed version of python doesn't impact what's in the tar.gz.

  • jmoreno
    jmoreno over 10 years
    Looks clean and promising, I need something like this for a no-root environment, hope it works!
  • Dmitry Wojciechowski
    Dmitry Wojciechowski over 10 years
    @tahoe, is it possible to put the folder with python into the directory with other name, not the same as one on the first computer? Are there any workarounds?
  • tahoe
    tahoe over 10 years
    It should be possible but you would need to edit the activate script to point to the right directory I think. Also I need to note that this works best if it's done on very similar systems as I ran into a problem with doing it this way between Ubuntu and CentOS where the SSL packages were compiled against quite different versions and would not load.
  • DKG
    DKG about 10 years
    This solution works fine. Note : Make sure to check the GNU libc version. If you compile python on linux with GNU libc 2.14 and try to run on another linux machine with GNU libc 2.5 it give error.
  • AzureIP
    AzureIP almost 3 years
    Could you please explain the difference between libc without Version number and with one?
  • AzureIP
    AzureIP almost 3 years
    What does setuptools does in this case?
  • AzureIP
    AzureIP almost 3 years
    How did you do that? How to build the same thing for newer Python versions?