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
    link
    fedilink
    arrow-up
    1
    ·
    19 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
      link
      fedilink
      arrow-up
      1
      ·
      17 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
        link
        fedilink
        arrow-up
        1
        ·
        edit-2
        17 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.