Coder Social home page Coder Social logo

pip.wtf's Introduction

pip.wtf: Inline dependencies for small Python scripts.

# https://pip.wtf
def pip_wtf(command):
    import os, os.path, sys
    t = os.path.join(os.path.dirname(os.path.abspath(__file__)), ".pip_wtf." + os.path.basename(__file__))
    sys.path = [p for p in sys.path if "-packages" not in p] + [t]
    os.environ["PATH"] = t + os.path.sep + "bin" + os.pathsep + os.environ["PATH"]
    os.environ["PYTHONPATH"] = os.pathsep.join(sys.path)
    if os.path.exists(t): return
    os.system(" ".join([sys.executable, "-m", "pip", "install", "-t", t, command]))

On GitHub and pip.wtf. Quick start: curl -sL pip.wtf/raw


I've had it. I just wanted to write a single-file Python script with one measly little external import. But the Python dependency management cabal just won't stop treating me like I'm an idiot.

Pipx? Not for scripts. Poetry? "Oh, poor baby, did you forget your pyproject.toml?" Pip-run? Tired of fighting with persistence. Pip by itself with a little -U? I've gotta give them an extra flag to show I know how to wipe my own ass! What about baking it in to pip? If the rabble can ever settle on anything, even more TOML, it'll only work with a version of pip that's definitely not gonna be around on my ancient Debian VPS!

Well, Python, you've done it. I'm pissed. I'm giving up on you...r suite of god-awful, overbearing package managers and I'm going to do it myself, in my script, with no virtual environments, no pip wrappers, and no god damn TOML!

That's pip_wtf: a single function you copy to the top of your Python script. It needs pip and that's it. You call it just once, with a string containing the back half of a pip install command, then do your imports, and then you've got a script that works on pretty much every platform and pretty much every Python version since 2.7 (as long as pip is around).

#!/usr/bin/env python3

# https://pip.wtf
def pip_wtf(command):
    import os, os.path, sys
    t = os.path.join(os.path.dirname(os.path.abspath(__file__)), ".pip_wtf." + os.path.basename(__file__))
    sys.path = [p for p in sys.path if "-packages" not in p] + [t]
    os.environ["PATH"] = t + os.path.sep + "bin" + os.pathsep + os.environ["PATH"]
    os.environ["PYTHONPATH"] = os.pathsep.join(sys.path)
    if os.path.exists(t): return
    os.system(" ".join([sys.executable, "-m", "pip", "install", "-t", t, command]))

# Now you just call it to install your packages:
#   pip_wtf('the rest of the pip install command here')
# Here are some examples for different platforms:

import sys
if sys.version_info >= (3, 5):
    # You gotta shell-escape your requirements if they would break on the terminal.
    # If you're on Windows, remember Windows needs double-quotes, not single.
    pip_wtf('beautifulsoup4 "requests>=1.0" pyyaml==5.3.1')

elif sys.version_info >= (3, 0):
    # You can add anything else you want to the pip install command to help add
    # special flags for difficult situations, like when the Pip version is too old
    # to support automatic https URLs...
    pip_wtf('--index-url https://pypi.python.org/simple/ beautifulsoup4==4.2.1 requests==2.13.0 pyyaml==3.10 urllib3==2.0.5')

else:
    # It even works with Python 2.7 (kinda tough to find an environment with that these days).
    pip_wtf('beautifulsoup4 requests pyyaml')

import requests
import yaml
from bs4 import BeautifulSoup
soup = BeautifulSoup(requests.get("https://pypi.org").content, "html.parser")
print(yaml.dump({"header": soup.find("h1").get_text()}))

How's it work? Well, for /home/adder/bin/bite.py:

  1. All pip_wtf() packages get installed into /home/adder/bin/.pip_wtf.bite.py on first run
  2. Further runs do nothing if that directory already exists, so you have to either clean it up yourself or change the function
  3. The script's sys.path (where it looks for modules) includes the .pip_wtf... directory and ignores all other site-packages directories just like a virtualenv would
  4. The script's PATH (where subprocesses look for binaries) includes the .pip_wtf... directory
  5. The script's PYTHONPATH (where subprocess's binaries will look for Python modules) includes the .pip_wtf... directory

You're totally in charge of the new directory and the pip_wtf behavior.

  • New dependency? You need to rm -rf it first.
  • Prefer to upgrade packages instead? Comment out the early return.
  • Need to support site-packages or dist-packages too? Change that list comprehension.
  • Want to share dependencies across your seventeen pytorch scripts? Lose the early return and change t so it's one .pip_wtf/ for your whole script directory, or import it, or something. Do what you want, dude! It's all right there!

Finally. Python dependencies that follow your orders instead of the other way around.

pip.wtf's People

Contributors

actions-user avatar sabslikesobs avatar

Stargazers

Enric Meinhardt avatar Sheldon Rupp avatar Nsukami _ avatar Amal Khailtash avatar Ove Ragnar Oddløkken avatar  avatar  avatar Robert Korzeniec avatar Lorenzo Veronese avatar Thibaud Gambier avatar AG avatar Enrico Marchesin avatar Debakar Roy avatar stahl avatar Birdie avatar Eric Le Nay avatar Jayaseelan Yezhuaralai avatar Den35E avatar Milkii Brewster avatar Maic Siemering avatar  avatar Alexander Kammerer avatar Moayad Shammout avatar Andreas Motl avatar António P. P. Almeida avatar Ken Harrison avatar  avatar Jon Palle Hansen avatar Andrew Ross avatar Paolo Betti avatar D. Bohdan avatar weiyang avatar Suresh Prajapati avatar Дмитрий avatar Muzuwi avatar Ng Han Seng avatar Bear Huang avatar Frog Chen avatar

Watchers

 avatar Enric Meinhardt avatar  avatar  avatar

Forkers

taspotts

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.