title: Using setup.py to install python project as a systemd service
body: <p>I have a python project and I want to be able to install it using something like <code>python setup.py install</code> so that the installation automatically creates a systemd service.</p>
  
  <p>I'm having some trouble, most probably setting the paths or imports correctly.</p>
  
  <blockquote>
    <p>My environment:</p>
    
    <ul>
    <li>Ubuntu 15.04</li>
    <li>Python 2.7 (although it would be great to make it work in py3 too).</li>
    </ul>
  </blockquote>
  
  <p>Project Structure:</p>
  
  <pre><code>+ top-folder
    + super_project
      + folder1
        __init__.py
        file1.py
      + folder2
        __init__.py
        file2.py
      __init__.py
      main.py
    setup.py
    setup.cfg
  </code></pre>
  
  <p>setup.py:</p>
  
  <pre><code>from setuptools.command.install import install
  from setuptools import setup, find_packages
  import subprocess
  import os
  
  
  class CustomInstallCommand(install):
  
    def run(self):
      install.run(self)
      current_dir_path = os.path.dirname(os.path.realpath(__file__))
      create_service_script_path = os.path.join(current_dir_path, 'super_project', 'install_scripts', 'create_service.sh')
      subprocess.check_output([create_service_script_path])
  
  setup(
    name='super-project',
    author='Myself',
    version='0.0.1',
    description='My Description',
    packages=find_packages(exclude=['contrib', 'docs']),
    # this will create the /usr/local/bin/super-project entrypoint script
    entry_points={
      'console_scripts': [
        'super-project = super_project.main:main'
      ]
    },
    cmdclass={'install': CustomInstallCommand}
  )
  </code></pre>
  
  <p>main.py</p>
  
  <pre><code>from super_project.folder1.file1 import Class1
  from super_project.folder2.file2 import Class2
  import logging
  
  
  def main():
    logging.info('Executing super-project...')
    (...)
    logging.info('super-project execution finished.')
  
  if __name__ == '__main__':
    main()
  </code></pre>
  
  <p>setup.cfg</p>
  
  <pre><code>[bdist_wheel]
  universal=1
  </code></pre>
  
  <p>create_service.sh (more or less):</p>
  
  <pre><code>SYSTEMD_SCRIPT_DIR=$( cd  $(dirname "${BASH_SOURCE:=$0}") &amp;&amp; pwd)
  cp -f "$SYSTEMD_SCRIPT_DIR/super-project.service" /lib/systemd/system
  chown root:root /lib/systemd/system/super-project.service
  
  systemctl daemon-reload
  systemctl enable super-project.service
  </code></pre>
  
  <p>super-project.service</p>
  
  <pre><code>[Unit]
  Description=Super Description
  
  [Service]
  Type=simple
  ExecStart=/usr/local/bin/super-service
  Restart=always
  
  [Install]
  WantedBy=multi-user.target
  </code></pre>
  
  <p>The installation of the package generates the following output:</p>
  
  <pre><code>$ sudo python setup.py install --record files.txt
  running install
  running build
  running build_py
  copying super_project/main.py - build/lib.linux-x86_64-2.7/super_project
  running install_lib
  copying build/lib.linux-x86_64-2.7/super_project/__init__.py - /usr/local/lib/python2.7/dist-packages/super_project
  copying build/lib.linux-x86_64-2.7/super_project/main.py - /usr/local/lib/python2.7/dist-packages/super_project
  copying build/lib.linux-x86_64-2.7/super_project/db/__init__.py - /usr/local/lib/python2.7/dist-packages/super_project/db
  copying build/lib.linux-x86_64-2.7/super_project/db/db_gateway.py - /usr/local/lib/python2.7/dist-packages/super_project/db
  (...)
  byte-compiling /usr/local/lib/python2.7/dist-packages/super_project/__init__.py to
  __init__.pyc
  byte-compiling /usr/local/lib/python2.7/dist-packages/super_project/main.py to
  main.pyc
  byte-compiling /usr/local/lib/python2.7/dist-packages/super_project/db/__init__.py to
  __init__.pyc
  byte-compiling /usr/local/lib/python2.7/dist-packages/super_project/db/db_gateway.py
  to db_gateway.pyc
  (...)
  running install_egg_info
  running egg_info
  writing requirements to super_project.egg-info/requires.txt
  writing super_project.egg-info/PKG-INFO
  writing top-level names to super_project.egg-info/top_level.txt
  writing dependency_links to super_project.egg-info/dependency_links.txt
  writing entry points to super_project.egg-info/entry_points.txt
  reading manifest file 'super_project.egg-info/SOURCES.txt'
  writing manifest file 'super_project.egg-info/SOURCES.txt'
  Copying super_project.egg-info to /usr/local/lib/python2.7/dist-packages/super_project-0.0.1.egg-info
  running install_scripts
  Installing ai-scenario-qa script to /usr/local/bin
  writing list of installed files to 'files.txt'
  </code></pre>
  
  <p>The <code>super-project</code> file is created in /usr/local/bin:</p>
  
  <pre><code>#!/usr/bin/python
  # EASY-INSTALL-ENTRY-SCRIPT: 'super-project==0.0.1','console_scripts','super-project'
  __requires__ = 'super-project==0.0.1'
  import sys
  from pkg_resources import load_entry_point
  
  if __name__ == '__main__':
      sys.exit(
          load_entry_point('super-project==0.0.1', 'console_scripts', 'super-project')()
      )
  </code></pre>
  
  <p>The installation seems successful, although:</p>
  
  <pre><code>$ systemctl status super-project.service
  ● super-project.service
     Loaded: not-found (Reason: No such file or directory)
     Active: inactive (dead)
  </code></pre>
  
  <p>The error I can see in /var/log/syslog:</p>
  
  <pre><code> Feb 16 20:48:34  systemd[1]: Starting  Super Description...
   Feb 16 20:48:34  super-project[22517]: Traceback (most recent call last):
   Feb 16 20:48:34  super-project[22517]: File "/usr/local/bin/super-project", line 9, in &lt;module
   Feb 16 20:48:34  super-project[22517]: load_entry_point('super-project==0.0.1', 'console_scripts', 'super-project')()
   Feb 16 20:48:34  super-project[22517]: File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 521, in load_entry_point
   Feb 16 20:48:34  super-project[22517]: return get_distribution(dist).load_entry_point(group, name)
   Feb 16 20:48:34  super-project[22517]: File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 2632, in load_entry_point
   Feb 16 20:48:34  super-project[22517]: return ep.load()
   Feb 16 20:48:34  super-project[22517]: File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 2312, in load
   Feb 16 20:48:34  super-project[22517]: return self.resolve()
   Feb 16 20:48:34  super-project[22517]: File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 2318, in resolve
   Feb 16 20:48:34  super-project[22517]: module = __import__(self.module_name, fromlist=['__name__'], level=0)
   Feb 16 20:48:34  super-project[22517]: ImportError: No module named main
   Feb 16 20:48:34  systemd[1]: super-project.service: main process exited, code=exited, status=1/FLURE
   Feb 16 20:48:34  systemd[1]: Unit super-project.service entered fled state.
   Feb 16 20:48:34  systemd[1]: super-project.service failed.
   Feb 16 20:48:34  systemd[1]: super-project.service holdoff time over, scheduling restart.
   Feb 16 20:48:34  systemd[1]: start request repeated too quickly for super-project.service
   Feb 16 20:48:34  systemd[1]: Failed to start Super Description.
   Feb 16 20:48:34  systemd[1]: Unit super-project.service entered fled state.
   Feb 16 20:48:34  systemd[1]: super-project.service failed.
  </code></pre>
  
  <p><strong>As can be seen, the module <code>main</code> cannot be found</strong>. This is the main problem.</p>
  
  <p>When changing code/conf, I remove the super-project/service as follows:</p>
  
  <pre><code>$ sudo systemctl disable super-project.service
  $ sudo rm -f /lib/systemd/system/super-project.service
  $ sudo systemctl daemon-reload
  $ su
  # cat files.txt | xargs rm -r
  </code></pre>
  
  <p>On the other hand:</p>
  
  <ul>
  <li>If I execute <code>$ super-project</code> from <code>/usr/local/bin/</code>, the script starts correctly (no import exception) but the configuration files cannot be read (most probably because of relative/absolute path issues).</li>
  <li><strong>If I execute <code>$ super-project</code> from <code>top-folder</code> (folder containing the project code/files) the script runs perfectly</strong></li>
  </ul>
  
  <p>What am I missing? I've spend a lot of time searching what the issue might be. It seems that the package is correctly set up in the <code>dist-packages</code> directory and all the service files are correctly created once the setup is executed.</p>
  
  <p>I've read things about using <code>from __future__ import absolute_import</code>, but I'm not sure if I have to add that to my main.py (it does not work) or to all the files in my project.</p>