Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

setup.py: installing just a pth file?

Tags:

python

As the final step in building a custom python, I need to add a myproject.pth.

Currently I'm doing this in a Makefile:

install:
        rm -f            ../../lib/python2.6/site-packages/myproject.pth
        cp myproject.pth ../../lib/python2.6/site-packages/myproject.pth

but I would like to encapsulate this in a setup.py. Unfortuntately the setup.py docs don't seem to cover this trivial case! Any help appreciated. I tried this but it doesn't work:

from setuptools import setup
setup(
    packages=['mypackage_pth'],
    package_dir={'mypackage_pth': '.'},
    package_data={'mypackage_pth': ['mypackage.pth']},
)
like image 376
Mark Harrison Avatar asked Jan 27 '10 09:01

Mark Harrison


People also ask

How do I install .py files?

To install a package that includes a setup.py file, open a command or terminal window and: cd into the root directory where setup.py is located. Enter: python setup.py install.

Where do I put .PTH files in Python?

pth file to any directory on the python path: "The most convenient way is to add a path configuration file to a directory that's already on Python's path, usually to the .../site-packages/ directory." I've done that and you're right it doesn't work!

What is PTH file in Python?

A PTH file is a machine learning model created using PyTorch, an open-source machine learning library. It contains algorithms used to automatically perform a task, such as upscaling or identifying an image.


3 Answers

You're looking for the data_files parameter to setup:

from distutils import sysconfig
site_packages_path = sysconfig.get_python_lib()

setup(...,
  data_files=[(site_packages_path, ["mypackage.pth"])]
 )
like image 55
stderr Avatar answered Nov 08 '22 11:11

stderr


Adapted from stderr's answer. Not sure if you're supposed to do this, but it works.

from distutils import sysconfig
site_packages_path = sysconfig.get_python_lib()

import shutil
shutil.copy('mypackage.pth', site_packages_path)

setup(...)
like image 26
S. Wolf Avatar answered Nov 08 '22 11:11

S. Wolf


The right thing to do here, is to extend setuptools' build_py, and copy the pth file into the directory into the build directory, in the location where setuptools prepares all the files that go into site-packages there.

from setuptools.command.build_py import build_py


class build_py_with_pth_file(build_py):
     """Include the .pth file for this project, in the generated wheel."""

     def run(self):
         super().run()

         destination_in_wheel = "mypackage.pth"
         location_in_source_tree = "src/mypackage.pth"
 
         outfile = os.path.join(self.build_lib, destination_in_wheel)
         self.copy_file(location_in_source_tree, outfile, preserve_mode=0)

setup(
   ...,
   cmdclass={"build_py": build_py_with_pth_file},
)

All the other answers here (at the time of writing) are wrong in subtle ways.

data_files=[(site_packages_path, ["mypackage.pth"])]

This is semantically wrong -- the pth file is NOT data. It's code, much like how the various .py files in the rest of your project are code. More importantly, this is also functionally broken -- in a slightly subtle but important manner.

This embeds the site_packages_path into the wheel. You'll end up with a wheel containing a file path like:

my_package-1.0.0.data/data/lib/python3.9/site-packages/mypackage.pth

This wheel will only work on Python 3.9 (because that's what the path is) but it will be very easy to tag as py3 (i.e. compatible with all Python versions).

This is non-trivial to detect, since you'll need a development workflow that runs tests across multiple different Python versions, using the generated wheel.

shutil.copy('mypackage.pth', site_packages_path)

This is... bad.

While it will work across Python versions, this will "install" the pth file even if a user downloads the project, with pip download mypackage.

More importantly, a wheel generated for this project will not have any pth file associated with the project. So, subsequent installations will be not get the pth file installed (since pip will cache locally built wheels).

This can't be reproduced by installing from the source directory locally and is similarly non-trivial: This is non-trivial to detect, since you'll need a development workflow that installs the package in a different environment than the one you've built it from, to run the tests in a manner that they can detect this.

like image 39
pradyunsg Avatar answered Nov 08 '22 11:11

pradyunsg