{"id":7846,"library":"varname","title":"Varname","description":"Varname is a Python library that provides 'dark magics' to retrieve the names of variables, arguments, and expressions at runtime. It's currently at version 0.15.1, offering functions like `varname()`, `nameof()`, and `argname()` to simplify introspection and debugging. The library maintains an active release cadence, with recent updates focusing on improved expression parsing and Python version compatibility.","status":"active","version":"0.15.1","language":"en","source_language":"en","source_url":"https://github.com/pwwang/python-varname","tags":["introspection","debugging","metaprogramming","variable names","AST"],"install":[{"cmd":"pip install varname","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Core dependency for AST analysis, updated to v2.2.1 to fix Python 3.13 issues.","package":"executing","optional":false},{"reason":"Used for AST parsing, updated to version 3.0.0 in varname 0.14.0.","package":"asttokens","optional":false}],"imports":[{"symbol":"varname","correct":"from varname import varname"},{"note":"`nameof` is directly available from the top-level package since 0.15.0, after being deprecated and re-introduced.","wrong":"from varname.core import nameof","symbol":"nameof","correct":"from varname import nameof"},{"symbol":"argname","correct":"from varname import argname"},{"symbol":"jsobj","correct":"from varname.helpers import jsobj"},{"note":"Use `exec_code` instead of Python's built-in `exec` when using `varname` to ensure source code is available at runtime.","wrong":"exec(code_string)","symbol":"exec_code","correct":"from varname.helpers import exec_code"},{"note":"Useful for explicitly retaining variable names in dynamic contexts like loops.","symbol":"Wrapper","correct":"from varname.helpers import Wrapper"}],"quickstart":{"code":"import varname\n\ndef func():\n    # varname() retrieves the name of the variable it's assigned to.\n    return varname()\n\nx = 0\na = [object] * 5\n\n# Before v0.15.1, this might raise ImproperUseError.\n# Now, it correctly prints 'a[x + 1]' (which evaluates to a[1]).\na[x + 1] = func()\nprint(f\"Value at a[1]: {a[1]}\")\n\n# Demonstrating other new subscript supports from v0.15.1\nb = []\nb.append(func())\nprint(f\"Element in b: {b[0]}\") # prints 'b.append(func())'\n\n# Using nameof to get an argument's name\ndef process(my_arg):\n    return varname.nameof(my_arg)\n\nresult = process(x)\nprint(f\"Name of argument 'x': {result}\")\n\n# Using argname to get argument names within a function\ndef greet(name, message):\n    return varname.argname('name', 'message')\n\narg_names = greet('Alice', 'Hello')\nprint(f\"Argument names in greet: {arg_names}\") # {'name': 'name', 'message': 'message'}\n","lang":"python","description":"This quickstart demonstrates the core `varname()` functionality, including the enhanced subscript support introduced in v0.15.1, and basic usage of `nameof()` and `argname()`."},"warnings":[{"fix":"Adjust code expecting only the root variable name for attribute chains. If the old behavior is strictly required, pin `varname<0.13.0`.","message":"In `varname` versions 0.13.0 and later, calling `varname()` on an attribute chain like `a.b` will return the full chain `\"a.b\"` instead of just the root variable name `\"a\"`.","severity":"breaking","affected_versions":">=0.13.0"},{"fix":"If you were on `0.14.0` and `nameof` was removed, upgrade to `varname>=0.15.0` to regain its functionality. If you were considering migrating from `nameof` due to the deprecation warning in `0.13.4`, note that it has been brought back.","message":"`nameof` was deprecated in version 0.14.0 (warned in 0.13.4), leading to its removal in that version. It was subsequently re-introduced in version 0.15.0.","severity":"deprecated","affected_versions":"0.14.0"},{"fix":"Upgrade to `varname>=0.15.1` for enhanced subscript support that handles dynamic indexing and more complex expressions.","message":"Prior to version 0.15.1, using `varname()` within complex subscript assignments (e.g., `a[x + 1] = func()`) would raise an `ImproperUseError` due to limitations in parsing complex expressions.","severity":"gotcha","affected_versions":"<0.15.1"},{"fix":"Avoid using `varname` in code executed via `exec()`. For such scenarios, use `varname.helpers.exec_code()` instead of the built-in `exec()` to ensure source code is available at runtime, which `varname` can then analyze.","message":"`varname` relies heavily on AST analysis via the `executing` package, which may not work reliably with environments using other AST manipulation techniques or dynamic code execution like Python's built-in `exec()` function, `macropy`, `birdseye`, or `reticulate`.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Upgrade to `varname>=0.15.1` for better support of complex expressions. If upgrading is not an option, simplify the expression where `varname()` is called, or assign its result to a simple variable first.","cause":"This error often occurs when `varname()` is called within complex expressions, especially in versions prior to 0.15.1 when used in array/list subscripts or other non-direct assignments.","error":"ImproperUseError: varname() is used improperly."},{"fix":"Upgrade to `varname>=0.15.0` to restore `nameof` functionality, as it was re-introduced in this version. Alternatively, refactor your code to use `varname.argname()` which can often achieve similar results, or use `varname()` if appropriate.","cause":"This specific error indicates that you are likely using `varname==0.14.0`, where the `nameof` function was temporarily removed after deprecation.","error":"AttributeError: module 'varname' has no attribute 'nameof'"},{"fix":"For scenarios where `varname.varname()` struggles, consider using `varname.helpers.Wrapper` to explicitly associate a value with its variable name. Example: `from varname.helpers import Wrapper; a = Wrapper(''); mydict = {val.name: val.value for val in [a]}`.","cause":"`varname` can sometimes struggle to reliably retrieve variable names when they are created dynamically, assigned implicitly within loops (e.g., in a list comprehension or tight loop constructs), or when the assignment context is not a direct variable assignment.","error":"NameError: name 'my_variable' is not defined (when using varname inside certain loops or comprehensions)"},{"fix":"Ensure you are passing `code`, `globals` (e.g., `globals().copy()`), `locals` (e.g., `locals().copy()`) and any other specified arguments according to the current `varname` documentation. Avoid passing `sourcefile` unless explicitly required and documented for public API usage.","cause":"This may occur if `varname.helpers.exec_code()` is called with incorrect arguments or an older signature. The `sourcefile` argument, while present in some internal uses, might not be intended for direct user calls or its position changed.","error":"TypeError: exec_code() got an unexpected keyword argument 'sourcefile'"}]}