{"id":248,"library":"six","title":"six","description":"six is a Python 2 and 3 compatibility library that provides utility functions for smoothing over differences between the two Python versions, enabling codebases to run on both without modification. It consists of a single Python file (six.py) covering string types, integer types, standard library moves, metaclass helpers, and more. Current version is 1.17.0, released December 2024. The project is in maintenance mode: Python 2 reached end-of-life in 2020, and in 2024 it is entirely normal for projects to support only Python 3, so new code should not take a dependency on six — it is primarily relevant for maintaining legacy dual-version codebases or as a transitive dependency.","status":"maintenance","version":"1.17.0","language":"python","source_language":"en","source_url":"https://github.com/benjaminp/six","tags":["compatibility","python2","python3","utilities","stdlib","legacy","maintenance"],"install":[{"cmd":"pip install six","lang":"bash","label":"pip"}],"dependencies":[],"imports":[{"note":"Top-level import; all constants, helpers, and the moves virtual module are accessed as attributes of the six module object.","symbol":"six","correct":"import six"},{"note":"On Python 2 string_types is (basestring,); on Python 3 it is (str,). Using bare str misses unicode on Py2.","wrong":"isinstance(value, str)","symbol":"string_types / text_type / binary_type","correct":"import six\nisinstance(value, six.string_types)"},{"note":"six.moves is a virtual module implemented via a PEP 302 meta path hook inside six.py — there is no moves.py on disk. Direct 'import six.moves' can fail with ModuleNotFoundError in some environments (frozen importers, vendored copies, Python 3.12+). Always use 'from six.moves import <name>'.","wrong":"import six.moves","symbol":"six.moves (stdlib remaps)","correct":"from six.moves import urllib\nfrom six.moves import range\nfrom six.moves import configparser"},{"note":"Use with_metaclass() or the @add_metaclass decorator only when the codebase must remain Py2-compatible; on Py3-only code use the native metaclass= keyword directly.","wrong":"class MyClass(object, metaclass=Meta): pass  # Py3-only syntax","symbol":"with_metaclass","correct":"from six import with_metaclass\nclass MyClass(with_metaclass(Meta, Base)): pass"},{"note":"Decorator alternative to with_metaclass; produces an equivalent class but applied post-construction.","symbol":"add_metaclass","correct":"from six import add_metaclass\n@add_metaclass(Meta)\nclass MyClass(object): pass"},{"note":"Wraps Python 3's 'raise value.with_traceback(tb)' syntax which is a SyntaxError on Python 2.","symbol":"reraise","correct":"from six import reraise\nreraise(tp, value, tb=None)"},{"note":"six.moves.urllib sub-namespaces (parse, request, response, error, robotparser) must be imported individually; accessing them as attributes of the moves.urllib object is unreliable without first importing the sub-module.","wrong":"from six.moves import urllib\nurllib.parse.urlencode(…)","symbol":"six.moves.urllib","correct":"from six.moves.urllib.parse import urlencode\nfrom six.moves.urllib.request import urlopen"}],"quickstart":{"code":"import six\nfrom six.moves import urllib\nfrom six.moves.urllib.parse import urlencode\n\n# Version guard\nif six.PY2:\n    print(\"Running on Python 2\")\nelse:\n    print(\"Running on Python 3\")\n\n# Cross-version type check\nvalue = u\"hello\"\nassert isinstance(value, six.text_type)        # unicode on Py2, str on Py3\nassert isinstance(b\"bytes\", six.binary_type)  # str on Py2, bytes on Py3\nassert isinstance(value, six.string_types)    # catches both str/unicode on Py2\n\n# Stdlib move: urllib.parse.urlencode works on both versions\nparams = urlencode({\"key\": \"value\", \"foo\": \"bar\"})\nprint(\"Encoded:\", params)\n\n# Integer types (int + long on Py2, int only on Py3)\nassert isinstance(42, six.integer_types)\n\n# Metaclass compatibility\nfrom six import with_metaclass\nclass Meta(type):\n    pass\nclass MyBase(with_metaclass(Meta, object)):\n    pass\nprint(\"Metaclass:\", type(MyBase))\n","lang":"python","description":"Demonstrate the most common six patterns: version guards, type checks, and stdlib moves."},"warnings":[{"fix":"Remove six and use Python 3 native equivalents. Tools like 'pyupgrade' and 'ruff --select UP' can automate the removal of six patterns.","message":"six exists solely to support Python 2/3 dual-compatibility. Python 2 reached end-of-life in January 2020. New projects targeting Python 3 only should not use six — use native Python 3 syntax instead (e.g. 'class Foo(metaclass=Meta)', 'from urllib.parse import urlencode', f-strings, etc.).","severity":"deprecated","affected_versions":"all"},{"fix":"Always use the current PyPI release (1.17.0). If a dependency vendors its own stale six, override it in sys.modules before importing that library: import six; import sys; sys.modules['lib.vendor.six'] = six","message":"six.moves is a virtual module backed by a meta path hook in six.py — there is no moves.py file on disk. In environments with frozen importers, custom loaders, or when a vendored/stale copy of six is present (e.g. inside a third-party library's vendor folder), 'import six.moves' or 'from six.moves import X' can raise ModuleNotFoundError even though 'import six' succeeds.","severity":"breaking","affected_versions":"< 1.16.0 (vendored copies); also surfaces on Python 3.12+"},{"fix":"Rename your file or variable. Check with: python -c \"import six; print(six.__file__)\" to verify the correct module is being loaded.","message":"Naming any of your own files 'six.py' or any variable 'six' shadows the installed library and causes confusing ImportError or AttributeError failures downstream.","severity":"gotcha","affected_versions":"all"},{"fix":"Use 'from six.moves.urllib.parse import urlencode' etc., rather than 'from six.moves import urllib' followed by 'urllib.parse.urlencode()'.","message":"six.moves.urllib sub-modules (parse, request, error, response, robotparser) must each be explicitly imported before use. Accessing them as attributes of a previously imported 'urllib' alias from six.moves is not reliably populated until the sub-module is imported.","severity":"gotcha","affected_versions":"all"},{"fix":"Use six >= 1.8.0. Prefer with_metaclass() over add_metaclass() when __slots__ are involved, or switch to Python 3 native metaclass= syntax.","message":"six.add_metaclass() with __slots__ containing '__weakref__' or '__dict__' was silently broken before 1.8.0 — the decorator re-created the class without preserving slot semantics correctly.","severity":"gotcha","affected_versions":"< 1.8.0"},{"fix":"Use the underscore-separated Python 3 name: 'from six.moves import html_parser'. Refer to https://six.readthedocs.io/#module-six.moves for the full mapping table.","message":"six.moves aliases follow Python 3 naming conventions with dots replaced by underscores (e.g. html.parser → html_parser, http.client → http_client). Importing the Python 2 module name directly (e.g. 'from six.moves import HTMLParser') will raise ImportError.","severity":"gotcha","affected_versions":"all"},{"fix":"Use 'import sys; sys.version_info >= (3, 4)' for version gating instead of six.PY34.","message":"six.PY34 (a constant that was True when running on Python 3.4+) was present in some versions and relied upon by downstream libraries but is not part of the documented public API. It was removed in later releases, breaking code that imported it directly.","severity":"gotcha","affected_versions":"mixed; PY34 was undocumented and has been removed"}],"env_vars":null,"last_verified":"2026-05-12T12:19:35.734Z","next_check":"2026-06-25T00:00:00.000Z","problems":[{"fix":"pip install six","cause":"The `six` library is not installed in the Python environment being used.","error":"ModuleNotFoundError: No module named 'six'"},{"fix":"from six.moves import StringIO","cause":"`six.moves` provides a Python 2/3 compatible `StringIO` class, but does not expose `cStringIO` directly, which was a Python 2-specific module.","error":"ImportError: cannot import name 'cStringIO' from 'six.moves'"},{"fix":"Use `six.ensure_binary(your_string)` or `six.b(your_string)` to explicitly convert the string to a bytes object for Python 2/3 compatibility.","cause":"Code intended for Python 2 (where `str` was bytes) is run in Python 3 (where `str` is Unicode), and a function expects actual bytes.","error":"TypeError: a bytes-like object is required, not 'str'"},{"fix":"Use `six.iteritems(my_dict)` for Python 2/3 compatible iteration, or `my_dict.items()` if the codebase is Python 3 only.","cause":"In Python 3, dictionary methods like `iteritems()` were removed, replaced by `items()`, which return view objects.","error":"AttributeError: 'dict' object has no attribute 'iteritems'"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":80,"quickstart_tag":"verified","pypi_latest":null,"install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":0.3,"disk_size":"17.8M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0,"mem_mb":0.3,"disk_size":"18M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":0.6,"disk_size":"19.7M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":0.6,"disk_size":"20M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":0.3,"disk_size":"11.6M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":0.3,"disk_size":"12M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":0.4,"disk_size":"11.2M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":0.2,"disk_size":"12M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":0.7,"disk_size":"17.3M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":0.7,"disk_size":"18M"}]},"quickstart_checks":{"last_tested":"2026-04-23","tag":"verified","tag_description":"quickstart runs on critical runtimes, recently tested","results":[{"runtime":"python:3.10-alpine","exit_code":0},{"runtime":"python:3.10-slim","exit_code":0},{"runtime":"python:3.11-alpine","exit_code":0},{"runtime":"python:3.11-slim","exit_code":0},{"runtime":"python:3.12-alpine","exit_code":0},{"runtime":"python:3.12-slim","exit_code":0},{"runtime":"python:3.13-alpine","exit_code":0},{"runtime":"python:3.13-slim","exit_code":0},{"runtime":"python:3.9-alpine","exit_code":0},{"runtime":"python:3.9-slim","exit_code":0}]}}