python.md

  1---
  2title: Python
  3description: "Configure Python language support in Zed, including language servers, formatting, and debugging."
  4---
  5
  6# How to Set Up Python in Zed
  7
  8Python support is available natively in Zed.
  9
 10- Tree-sitter: [tree-sitter-python](https://github.com/zed-industries/tree-sitter-python)
 11- Language Servers:
 12  - [DetachHead/basedpyright](https://github.com/DetachHead/basedpyright)
 13  - [astral-sh/ruff](https://github.com/astral-sh/ruff)
 14  - [astral-sh/ty](https://github.com/astral-sh/ty)
 15  - [microsoft/pyright](https://github.com/microsoft/pyright)
 16  - [python-lsp/python-lsp-server](https://github.com/python-lsp/python-lsp-server) (PyLSP)
 17- Debug Adapter: [debugpy](https://github.com/microsoft/debugpy)
 18
 19## Install Python
 20
 21You'll need both Zed and Python installed before you can begin.
 22
 23### Step 1: Install Python
 24
 25Zed does not bundle a Python runtime, so you’ll need to install one yourself.
 26Choose one of the following options:
 27
 28- uv (recommended)
 29
 30```bash
 31curl -LsSf https://astral.sh/uv/install.sh | sh
 32```
 33
 34To learn more, visit [Astral’s installation guide](https://docs.astral.sh/uv/getting-started/installation/).
 35
 36- Homebrew:
 37
 38```bash
 39brew install python
 40```
 41
 42- Python.org installer: Download the latest version from [python.org/downloads](https://python.org/downloads).
 43
 44### Step 2: Verify Python Installation
 45
 46Confirm Python is installed and available in your shell:
 47
 48```bash
 49python3 --version
 50```
 51
 52You should see an output like `Python 3.x.x`.
 53
 54## Open Your First Python Project in Zed
 55
 56Once Zed and Python are installed, open a folder containing Python code to start working.
 57
 58### Step 1: Launch Zed with a Python Project
 59
 60Open Zed.
 61From the menu bar, choose File > Open Folder, or launch from the terminal:
 62
 63```bash
 64zed path/to/your/project
 65```
 66
 67Zed will recognize `.py` files automatically using its native tree-sitter-python parser, with no plugins or manual setup required.
 68
 69### Step 2: Use the Integrated Terminal (Optional)
 70
 71Zed includes an integrated terminal, accessible from the bottom panel. If Zed detects that your project is using a [virtual environment](#virtual-environments), it will be activated automatically in newly-created terminals. You can configure this behavior with the [`detect_venv`](../reference/all-settings.md#terminal-detect_venv) setting.
 72
 73## Configure Python Language Servers in Zed
 74
 75Zed provides several Python language servers out of the box. By default, [basedpyright](https://github.com/DetachHead/basedpyright) is the primary language server, and [Ruff](https://github.com/astral-sh/ruff) is used for formatting and linting.
 76
 77Other built-in language servers are:
 78
 79- [ty](https://docs.astral.sh/ty/)—Up-and-coming language server from Astral, built for speed.
 80- [Pyright](https://github.com/microsoft/pyright)—The basis for basedpyright.
 81- [PyLSP](https://github.com/python-lsp/python-lsp-server)—A plugin-based language server that integrates with tools like `pycodestyle`, `autopep8`, and `yapf`.
 82
 83These are disabled by default, but can be enabled in your settings.
 84
 85Configure language servers in Settings ({#kb zed::OpenSettings}) under Languages > Python, or add to your settings file:
 86
 87```json [settings]
 88{
 89  "languages": {
 90    "Python": {
 91      "language_servers": [
 92        // Disable basedpyright and enable ty, and otherwise
 93        // use the default configuration.
 94        "ty",
 95        "!basedpyright",
 96        "..."
 97      ]
 98    }
 99  }
100}
101```
102
103See: [Working with Language Servers](https://zed.dev/docs/configuring-languages#working-with-language-servers) for more information about how to enable and disable language servers.
104
105### Basedpyright
106
107[basedpyright](https://docs.basedpyright.com/latest/) is the primary Python language server in Zed beginning with Zed v0.204.0. It provides core language server functionality like navigation (go to definition/find all references) and type checking. Compared to Pyright, it adds support for additional language server features (like inlay hints) and checking rules.
108
109Note that while basedpyright in isolation defaults to the `recommended` [type-checking mode](https://docs.basedpyright.com/latest/benefits-over-pyright/better-defaults/#typecheckingmode), Zed configures it to use the less-strict `standard` mode by default, which matches the behavior of Pyright. You can set the type-checking mode for your project using the `typeCheckingMode` setting in `pyrightconfig.json` or `pyproject.toml`, which will override Zed's default. Read on more for more details about how to configure basedpyright.
110
111#### Basedpyright Configuration
112
113basedpyright reads configuration options from two different kinds of sources:
114
115- Language server settings ("workspace configuration"), which must be configured per-editor (using `settings.json` in Zed's case) but apply to all projects opened in that editor
116- Configuration files (`pyrightconfig.json`, `pyproject.toml`), which are editor-independent but specific to the project where they are placed
117
118As a rule of thumb, options that are only relevant when using basedpyright from an editor must be set in language server settings, and options that are relevant even if you're running it [as a command-line tool](https://docs.basedpyright.com/latest/configuration/command-line/) must be set in configuration files. Settings related to inlay hints are examples of the first category, and the [diagnostic category](https://docs.basedpyright.com/latest/configuration/config-files/#diagnostic-categories) settings are examples of the second category.
119
120Examples of both kinds of configuration are provided below. Refer to the basedpyright documentation on [language server settings](https://docs.basedpyright.com/latest/configuration/language-server-settings/) and [configuration files](https://docs.basedpyright.com/latest/configuration/config-files/) for comprehensive lists of available options.
121
122##### Language server settings
123
124Language server settings for basedpyright in Zed can be set in the `lsp` section of your `settings.json`.
125
126For example, to:
127
128- diagnose all files in the workspace instead of the only open files default
129- disable inlay hints on function arguments
130
131You can use the following configuration:
132
133```json [settings]
134{
135  "lsp": {
136    "basedpyright": {
137      "settings": {
138        "basedpyright.analysis": {
139          "diagnosticMode": "workspace",
140          "inlayHints": {
141            "callArgumentNames": false
142          }
143        }
144      }
145    }
146  }
147}
148```
149
150##### Configuration files
151
152basedpyright reads project-specific configuration from the `pyrightconfig.json` configuration file and from the `[tool.basedpyright]` and `[tool.pyright]` sections of `pyproject.toml` manifests. `pyrightconfig.json` overrides `pyproject.toml` if configuration is present in both places.
153
154Here's an example `pyrightconfig.json` file that configures basedpyright to use the `strict` type-checking mode and not to issue diagnostics for any files in `__pycache__` directories:
155
156```json
157{
158  "typeCheckingMode": "strict",
159  "ignore": ["**/__pycache__"]
160}
161```
162
163### PyLSP
164
165[python-lsp-server](https://github.com/python-lsp/python-lsp-server/), more commonly known as PyLSP, by default integrates with a number of external tools (autopep8, mccabe, pycodestyle, yapf) while others are optional and must be explicitly enabled and configured (flake8, pylint).
166
167See [Python Language Server Configuration](https://github.com/python-lsp/python-lsp-server/blob/develop/CONFIGURATION.md) for more.
168
169## Virtual Environments
170
171[Virtual environments](https://docs.python.org/3/library/venv.html) are a useful tool for fixing a Python version and set of dependencies for a specific project, in a way that's isolated from other projects on the same machine. Zed has built-in support for discovering, configuring, and activating virtual environments, based on the language-agnostic concept of a [toolchain](../toolchains.md).
172
173Note that if you have a global Python installation, it is also counted as a toolchain for Zed's purposes.
174
175### Create a Virtual Environment
176
177If your project doesn't have a virtual environment set up already, you can create one as follows:
178
179```bash
180python3 -m venv .venv
181```
182
183Alternatively, if you're using `uv`, running `uv sync` will create a virtual environment the first time you run it.
184
185### How Zed Uses Python Toolchains
186
187Zed uses the selected Python toolchain for your project in the following ways:
188
189- Built-in language servers will be automatically configured with the path to the toolchain's Python interpreter and, if applicable, virtual environment. This is important so that they can resolve dependencies. (Note that language servers provided by extensions can't be automatically configured like this currently.)
190- Python tasks (such as pytest tests) will be run using the toolchain's Python interpreter.
191- If the toolchain is a virtual environment, the environment's activation script will be run automatically when you launch a new shell in Zed's integrated terminal, giving you convenient access to the selected Python interpreter and dependency set.
192- If a built-in language server is installed in the active virtual environment, that binary will be used instead of Zed's private automatically-installed binary. This also applies to debugpy.
193
194### Selecting a Toolchain
195
196For most projects, Zed will automatically select the right Python toolchain. In complex projects with multiple virtual environments, it might be necessary to override this selection. You can use the [toolchain selector](../toolchains.md#selecting-toolchains) to pick a toolchain from the list discovered by Zed, or [specify the path to a toolchain manually](../toolchains.md#adding-toolchains-manually) if it's not on the list.
197
198## Code Formatting & Linting
199
200Zed uses [Ruff](https://github.com/astral-sh/ruff) for formatting and linting Python code. Specifically, it runs Ruff as an LSP server using the `ruff server` subcommand.
201
202### Configuring Formatting
203
204Formatting in Zed follows a two-phase pipeline: first, code actions on format (`code_actions_on_format`) are executed, followed by the configured formatter.
205
206Configure formatting in Settings ({#kb zed::OpenSettings}) under Languages > Python, or add to your settings file:
207
208```json [settings]
209{
210  "languages": {
211    "Python": {
212      "code_actions_on_format": {
213        "source.organizeImports.ruff": true
214      },
215      "formatter": {
216        "language_server": {
217          "name": "ruff"
218        }
219      }
220    }
221  }
222}
223```
224
225These two phases are independent. For example, if you prefer [Black](https://github.com/psf/black) for code formatting, but want to keep Ruff's import sorting, you only need to change the formatter phase.
226
227Configure in Settings ({#kb zed::OpenSettings}) under Languages > Python, or add to your settings file:
228
229```json [settings]
230{
231  "languages": {
232    "Python": {
233      "code_actions_on_format": {
234        // Phase 1: Ruff still handles organize imports
235        "source.organizeImports.ruff": true
236      },
237      "formatter": {
238        // Phase 2: Black handles formatting
239        "external": {
240          "command": "black",
241          "arguments": ["--stdin-filename", "{buffer_path}", "-"]
242        }
243      }
244    }
245  }
246}
247```
248
249To completely switch to another tool and prevent Ruff from modifying your code at all, you must explicitly set `source.organizeImports.ruff` to false in the `code_actions_on_format` section, in addition to changing the formatter.
250
251To prevent any formatting actions when you save, you can disable format-on-save for Python files.
252
253Configure in Settings ({#kb zed::OpenSettings}) under Languages > Python, or add to your settings file:
254
255```json [settings]
256{
257  "languages": {
258    "Python": {
259      "format_on_save": "off"
260    }
261  }
262}
263```
264
265### Configuring Ruff
266
267Like basedpyright, Ruff reads options from both Zed's language server settings and configuration files (`ruff.toml`) when used in Zed. Unlike basedpyright, _all_ options can be configured in either of these locations, so the choice of where to put your Ruff configuration comes down to whether you want it to be shared between projects but specific to Zed (in which case you should use language server settings), or specific to one project but common to all Ruff invocations (in which case you should use `ruff.toml`).
268
269Here's an example of using language server settings in Zed's `settings.json` to disable all Ruff lints in Zed (while still using Ruff as a formatter):
270
271```json [settings]
272{
273  "lsp": {
274    "ruff": {
275      "initialization_options": {
276        "settings": {
277          "exclude": ["*"]
278        }
279      }
280    }
281  }
282}
283```
284
285And here's an example `ruff.toml` with linting and formatting options, adapted from the Ruff documentation:
286
287```toml
288[lint]
289# Avoid enforcing line-length violations (`E501`)
290ignore = ["E501"]
291
292[format]
293# Use single quotes when formatting.
294quote-style = "single"
295```
296
297For more details, refer to the Ruff documentation about [configuration files](https://docs.astral.sh/ruff/configuration/) and [language server settings](https://docs.astral.sh/ruff/editors/settings/), and the [list of options](https://docs.astral.sh/ruff/settings/).
298
299### Embedded Language Highlighting
300
301Zed supports syntax highlighting for code embedded in Python strings by adding a comment with the language name.
302
303```python
304# sql
305query = "SELECT * FROM users"
306
307#sql
308query = """
309    SELECT *
310    FROM users
311"""
312
313result = func( #sql
314    "SELECT * FROM users"
315)
316```
317
318## Debugging
319
320Zed supports Python debugging through the `debugpy` adapter. You can start with no configuration or define custom launch profiles in `.zed/debug.json`.
321
322### Start Debugging with No Setup
323
324Zed can automatically detect debuggable Python entry points. Press F4 (or run debugger: start from the Command Palette) to see available options for your current project.
325This works for:
326
327- Python scripts
328- Modules
329- pytest tests
330
331Zed uses `debugpy` under the hood, but no manual adapter configuration is required.
332
333### Define Custom Debug Configurations
334
335For reusable setups, create a `.zed/debug.json` file in your project root. This gives you more control over how Zed runs and debugs your code.
336
337- [debugpy configuration documentation](https://github.com/microsoft/debugpy/wiki/Debug-configuration-settings#launchattach-settings)
338
339#### Debug Active File
340
341```json [debug]
342[
343  {
344    "label": "Python Active File",
345    "adapter": "Debugpy",
346    "program": "$ZED_FILE",
347    "request": "launch"
348  }
349]
350```
351
352This runs the file currently open in the editor.
353
354#### Debug a Flask App
355
356For projects using Flask, you can define a full launch configuration:
357
358```
359.venv/
360app/
361  init.py
362  main.py
363  routes.py
364templates/
365  index.html
366static/
367  style.css
368requirements.txt
369```
370
371…the following configuration can be used:
372
373```json [debug]
374[
375  {
376    "label": "Python: Flask",
377    "adapter": "Debugpy",
378    "request": "launch",
379    "module": "app",
380    "cwd": "$ZED_WORKTREE_ROOT",
381    "env": {
382      "FLASK_APP": "app",
383      "FLASK_DEBUG": "1"
384    },
385    "args": [
386      "run",
387      "--reload", // Enables Flask reloader that watches for file changes
388      "--debugger" // Enables Flask debugger
389    ],
390    "autoReload": {
391      "enable": true
392    },
393    "jinja": true,
394    "justMyCode": true
395  }
396]
397```
398
399These can be combined to tailor the experience for web servers, test runners, or custom scripts.
400
401## Troubleshooting
402
403Issues with Python in Zed typically involve virtual environments, language servers, or tooling configuration.
404
405### Resolve Language Server Startup Issues
406
407If a language server isn't responding or features like diagnostics or autocomplete aren't available:
408
409- Check your Zed log (using the {#action zed::OpenLog} action) for errors related to the language server you're trying to use. This is where you're likely to find useful information if the language server failed to start up at all.
410- Use the language server logs view to understand the lifecycle of the affected language server. You can access this view using the {#action dev::OpenLanguageServerLogs} action, or by clicking the lightning bolt icon in the status bar and selecting your language server. The most useful pieces of data in this view are:
411  - "Server Logs", which shows any errors printed by the language server
412  - "Server Info", which shows details about how the language server was started
413- Verify your `settings.json` or `pyrightconfig.json` is syntactically correct.
414- Restart Zed to reinitialize language server connections, or try restarting the language server using the {#action editor::RestartLanguageServer}
415
416If the language server is failing to resolve imports, and you're using a virtual environment, make sure that the right environment is chosen in the selector. You can use "Server Info" view to confirm which virtual environment Zed is sending to the language server—look for the `* Configuration` section at the end.