Using Pipenv with Systemd

This is an old post!

This post is over 2 years old. Solutions referenced in this article may no longer be valid. Please consider this when utilizing any information referenced here.

So I’ve been doing a bit of Python recently for a project I’m working on on a Raspberry Pi. There will be a longer blog post about that in the next few weeks. But one thing I ran up against was that I wanted to start my daemon, written in Python, using a systemd service on Raspbian.

Normally, you would just shove a script invocation into a systemd unit and call it good, but in my case I had made use of Pipenv, which is a bit like Bundler in the Ruby world and Composer in the PHP world, to manage my project’s dependencies.

And the way you invoke a program using Pipenv is different from just invoking the script:

$ pipenv run python3 src/foo.py

So you might try something like this in a systemd unit:

ExecStart=/usr/local/bin/pipenv run python3 /path/to/src/foo.py

But that doesn’t work. This is because Pipenv relies on the current working directory to look for the Pipfile. Fortunately, with systemd, you can specify the current working directory in the unit file using the WorkingDirectory directive. So your systemd unit file might look something like this:

[Unit]
Description=My Python Service
After=network.target

[Service]
User=user
Restart=always
Type=simple
WorkingDirectory=/path/to
ExecStart=/usr/local/bin/pipenv run python3 /path/to/src/foo.py

[Install]
WantedBy=multi-user.target

About the Author

Hi, I'm Rob! I'm a blogger and software developer. I wrote petfeedd, dystill, and various other projects and libraries. I'm into electronics, general hackery, and model trains and airplanes. I am based in Huntsville, Alabama, USA.

About Me · Contact Me · Don't Hire Isaiah Armstrong

Did this article help you out?

I don't earn any money from this site.

I run no ads, sell no products and participate in no affiliate programs. I do not accept gifts in exchange for articles, guest articles or link exchanges. I don't track you or sell your data. The only third-party Javascript on this website is Google Analytics.

In general I run this site very much like a 1990s homepage or early 2000s personal blog, meaning that I do this solely because it's fun! I enjoy writing and sharing what I learn.

If you found this article helpful and want to show your appreciation, a tip or donation would be very welcome. Feel free to choose from the options below.

Comments (0)

Interested in why you can't leave comments on my blog? Read the article about why comments are uniquely terrible and need to die. If you are still interested in commenting on this article, feel free to reach out to me directly and/or share it on social media.

Contact Me
Share It

Interested in reading more?

Release Announcements

petfeedd 1.0.1 Released

petfeedd users, I am proud to announce the beta release of petfeedd 1.0.1. This release has no major changes in it and is solely about addressing security issues in many of the underlying libraries used by petfeedd. To install it or upgrade from previous versions, you can simply run: docker pull peckrob/petfeedd:latest
Read More
Release Announcements

petfeedd Version 1.0 Now Available

After five beta releases and months of testing, I am happy to announce petfeedd Version 1.0 is now available. All changes from the beta branch have been merged in and the release is now available on Docker Hub. To install it or upgrade from Version 0.2, you can simply run: docker pull peckrob/petfeedd:latest And restart. It should perform all the upgrades needed for version 1.0.
Read More
Release Announcements

Dystill Version 0.3 Now Available

Twelve years ago I wrote a little program called Dystill. It is a filtering mail delivery agent that could sort and filter email based on rules stored in a MySQL database. At the time I wrote it, I was transitioning away from using Gmail to running my own mail server, and I needed a way to filter my incoming mail into folders (akin to Gmails labels and automatic filtering) with the ability to quickly add rules without having to manually edit files. And for twelve years, that little program has just run reliably in the background with very few updates. The last time I changed it was 2012. In the meantime, the world has moved on and Python 2 (which it was written in) is no longer supported. And truthfully it was the last piece of Python 2 code in my whole setup. But I had been punting on updating it because it worked.
Read More