So, I have a python script I’d like to run from time to time from the CLI (on Linux) that resides inside a venv. What’s the recommended/intended way to do this?
Write a wrapper shell script and put it inside a $PATH-accessible directory that activates the virtual environment, runs the python script and deactivates the venv again? This seems a bit convoluted, but I can’t think of a better way.

    • Andy@programming.dev
      link
      fedilink
      arrow-up
      1
      ·
      13 days ago

      No, I don’t use GHA locally, but the actions are defined to run the same things that I do run locally (e.g. invoke nox). I try to keep the GHA-exclusive boilerplate to a minimum. Steps can be like:

      - name: fetch code
        uses: actions/checkout@v4
      
      - uses: actions/setup-python@v5
        with:
          allow-prereleases: true
          python-version: |
            3.13
            3.12
            3.11
            3.10
            3.9
            3.8
            3.7
      
      - run: pipx install nox
      
      - name: run ward tests in nox environment
        run: nox -s test test_without_toml combine_coverage --force-color
        env:
          PYTHONIOENCODING: utf-8
      
      - name: upload coverage data
        uses: codecov/codecov-action@v4
        with:
          files: ./coverage.json
          token: ${{ secrets.CODECOV_TOKEN }}
      

      Sometimes if I want a higher level interface to tasks that run nox or other things locally, I use taskipy to define them in my pyproject.toml, like:

      [tool.taskipy.tasks]
      fmt = "nox -s fmt"
      lock = "nox -s lock"
      test = "nox -s test test_without_toml typecheck -p 3.12"
      docs = "nox -s render_readme render_api_docs"
      
      • logging_strict@programming.dev
        link
        fedilink
        arrow-up
        1
        ·
        11 days ago

        Thanks for the introduction to taskipy. Think if i need macros, Makefile is the way to go. Supports running targets in parallel and i like performing a check to ensure the virtual environment is activated or the command won’t run.

        .ONESHELL:
        .DEFAULT_GOAL := help
        SHELL := /bin/bash
        APP_NAME := logging_strict
        
        #virtual environment. If 0 issue warning
        #Not activated:0
        #activated: 1
        ifeq ($(VIRTUAL_ENV),)
        $(warning virtualenv not activated)
        is_venv =
        else
        is_venv = 1
        VENV_BIN := $(VIRTUAL_ENV)/bin
        VENV_BIN_PYTHON := python3
        PY_X_Y := $(shell $(VENV_BIN_PYTHON) -c 'import platform; t_ver = platform.python_version_tuple(); print(".".join(t_ver[:2]));')
        endif
        
        .PHONY: mypy
        mypy:					## Static type checker (in strict mode)
        ifeq ($(is_venv),1)
        	@$(VENV_BIN_PYTHON) -m mypy -p $(APP_NAME)
        endif
        
        

        make mypy without the virtualenv on will write a warning message why it’s not working!

        • Andy@programming.dev
          link
          fedilink
          arrow-up
          1
          ·
          edit-2
          11 days ago

          Sure, but nox is the closer counterpart for in-venv-task definitions. List “sessions” with -l, pick specific sessions to run with -s.

          import nox
          from nox.sessions import Session
          
          nox.options.reuse_existing_virtualenvs = True
          APP_NAME = 'logging_strict'
          
          @nox.session(python='3.12')
          def mypy(session: Session):
              """Static type checker (in strict mode)"""
              session.install('-U', 'mypy', '.')
              session.run('mypy',  '-p', APP_NAME, *session.posargs)
          

          Unfortunately it doesn’t currently do any parallel runs, but if anyone wants to track/encourage/contribute in that regard, see nox#544.