{"library":"nplusone","title":"Nplusone","description":"Nplusone is a Python library designed to detect N+1 query problems in Object-Relational Mappers (ORMs) during development. It supports popular ORMs like SQLAlchemy, Peewee, and the Django ORM. The library monitors database interactions and emits warnings or raises exceptions when potentially inefficient lazy loads or unnecessary eager loads are detected. The current version is 1.0.0, released in May 2018, and it appears to have a low release cadence, indicating a mature and stable project.","language":"python","status":"active","last_verified":"Sat May 16","install":{"commands":["pip install nplusone"],"cli":null},"imports":["from nplusone.core.profiler import Profiler","from nplusone.ext.django import NPlusOneMiddleware","import nplusone.ext.sqlalchemy"],"auth":{"required":false,"env_vars":[]},"quickstart":{"code":"import logging\nfrom nplusone.core.profiler import Profiler\nimport nplusone.ext.sqlalchemy\n\n# Configure a logger to capture nplusone warnings\nlogger = logging.getLogger('nplusone')\nlogger.setLevel(logging.WARN)\nhandler = logging.StreamHandler()\nlogger.addHandler(handler)\n\n# --- Simulate an SQLAlchemy setup ---\nfrom sqlalchemy import create_engine, Column, Integer, String, ForeignKey\nfrom sqlalchemy.orm import sessionmaker, relationship\nfrom sqlalchemy.ext.declarative import declarative_base\n\nBase = declarative_base()\n\nclass Artist(Base):\n    __tablename__ = 'artists'\n    id = Column(Integer, primary_key=True)\n    name = Column(String)\n    songs = relationship('Song', back_populates='artist')\n\nclass Song(Base):\n    __tablename__ = 'songs'\n    id = Column(Integer, primary_key=True)\n    title = Column(String)\n    artist_id = Column(Integer, ForeignKey('artists.id'))\n    artist = relationship('Artist', back_populates='songs')\n\nengine = create_engine('sqlite:///:memory:')\nBase.metadata.create_all(engine)\nSession = sessionmaker(bind=engine)\nsession = Session()\n\n# Add some data\nartist1 = Artist(name='Artist One')\nartist2 = Artist(name='Artist Two')\nsession.add_all([artist1, artist2])\nsession.commit()\n\nsong1 = Song(title='Song A', artist=artist1)\nsong2 = Song(title='Song B', artist=artist1)\nsong3 = Song(title='Song C', artist=artist2)\nsession.add_all([song1, song2, song3])\nsession.commit()\n\n# --- Nplusone profiling ---\nprint('--- Starting nplusone profiling ---')\nwith Profiler():\n    songs = session.query(Song).all()\n    print(f'Fetched {len(songs)} songs.')\n    # This will trigger N+1 queries if artists are not eagerly loaded\n    for song in songs:\n        print(f'  Song: {song.title}, Artist: {song.artist.name}')\n\nprint('--- Profiling complete ---')\n\n# Example of how to raise an NPlusOneError for tests (optional)\n# from nplusone.core.exceptions import NPlusOneError\n# import os\n# os.environ['NPLUSONE_RAISE'] = 'True' # Set this environment variable or config option\n# try:\n#     with Profiler():\n#         songs = session.query(Song).all()\n#         for song in songs:\n#             _ = song.artist.name\n# except NPlusOneError as e:\n#     print(f'Caught expected NPlusOneError: {e}')\n# os.environ['NPLUSONE_RAISE'] = '' # Reset for other tests\n","lang":"python","description":"This quickstart demonstrates how to use `nplusone` with SQLAlchemy. It sets up a simple ORM model, adds some data, and then uses the `Profiler` context manager to detect N+1 queries when accessing related `Artist` objects within a loop without eager loading. Warnings will be logged to the console.","tag":null,"tag_description":null,"last_tested":null,"results":[]},"compatibility":{"tag":null,"tag_description":null,"last_tested":"2026-05-16","installed_version":"1.0.0","pypi_latest":"1.0.0","is_stale":false,"summary":{"python_range":"3.10–3.9","success_rate":100,"avg_install_s":1.6,"avg_import_s":0.04,"wheel_type":"wheel"},"results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"nplusone","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.03,"mem_mb":1.7,"disk_size":"18.1M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"nplusone","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":1.6,"import_time_s":0.02,"mem_mb":1.7,"disk_size":"19M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"nplusone","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.07,"mem_mb":2,"disk_size":"20.0M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"nplusone","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":1.7,"import_time_s":0.06,"mem_mb":2,"disk_size":"20M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"nplusone","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.05,"mem_mb":1.7,"disk_size":"11.9M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"nplusone","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":1.5,"import_time_s":0.06,"mem_mb":1.7,"disk_size":"12M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"nplusone","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.05,"mem_mb":2,"disk_size":"11.6M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"nplusone","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":1.5,"import_time_s":0.05,"mem_mb":1.8,"disk_size":"12M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"nplusone","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.03,"mem_mb":1.6,"disk_size":"17.6M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"nplusone","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":1.9,"import_time_s":0.03,"mem_mb":1.6,"disk_size":"18M"}]}}