# Python Tutorial: Ruff - A Fast Linter & Formatter to Replace Multiple Tools and Improve Code Quality

## Метаданные

- **Канал:** Corey Schafer
- **YouTube:** https://www.youtube.com/watch?v=828S-DMQog8
- **Дата:** 19.05.2025
- **Длительность:** 35:47
- **Просмотры:** 85,451
- **Источник:** https://ekstraktznaniy.ru/video/11705

## Описание

In this Python tutorial, we'll be learning how to use Ruff, a super-fast Python linter and formatter written in Rust. We'll cover how to install Ruff, how to use Ruff from the command line to check and fix your code, and how to configure Ruff both for individual projects and globally. You'll also learn how to integrate Ruff with VSCode to get real-time feedback as you code. Ruff is growing rapidly in popularity because it consolidates multiple Python tools like Flake8, Black, isort, and others into a single, faster solution that significantly improves code quality. By the end, you'll be equipped to use Ruff in your own Python projects. Let's get started...

Ruff Documentation -  https://docs.astral.sh/ruff/
Ruff Rules - https://docs.astral.sh/ruff/rules/
Pipx - https://pipx.pypa.io/stable/installation/

My Ruff Config - https://bit.ly/ruff-coreyms
My VS Code Settings - https://bit.ly/vscode-coreyms
        
UV Tutorial - https://youtu.be/AMdG7IjgSPM
Dotfiles Tutorial - https://youtu.be

## Транскрипт

### Segment 1 (00:00 - 05:00) []

Hey there. How's it going everybody? In this video, we're going to be learning how to use Rough. Ruff is a super fast Python liner and code formatter that's been growing pretty quickly in popularity lately. And I've been using it for some time now. And I've actually switched over to using it as my main llinter and formatter for Python, which has allowed me to replace a few other tools with just this one. And I've also noticed it's really improving my code quality. It's built by Astral, which is the same team behind the UV package manager that I covered in the last video. And just like UV, rough is super fast since it's written in Rust. If you haven't watched that last video yet, I'll leave a link to that video in the description section below. Uh, but you don't need to have seen that video in order to follow along with this one. So, I said that Rough is a llinter and formatter. If you don't know what those are, this is basically a tool designed to improve your Python code quality and consistency. But what makes Rough special is that it consolidates a ton of different Python tooling that you might already be using like Flake8 or Pyint for linting. Uh black for formatting, I sort for organizing imports, PI upgrade for modernizing your code, and a bunch of others. And it does all of this while being a lot faster than all of those other tools as well. So I thought it would be helpful to show you how to set this up so that you can get the most use out of it. In this video, I'll be showing you how to use Rough both through the command line and how to set this up in VS Code so that you can get real-time feedback. But first, we need to install this. So, let's go ahead and see how we can do that. So, there are several ways that we can install Rough. You can install it directly into your local project's virtual environment using pip. So, I could just say pip installer ruff. Now, this is a quick and easy way to get started, but the downside is that Rough won't be available for other projects unless you install it in each of their environments also. So, if we want this to be available in any project, we can install this globally. And there are a couple ways that we can do that. So, one popular option for installing command line tools like Rough is using pip X. Pip X installs P P P P Pythyon packages into isolated environments, but makes their command line interfaces available globally. Pipex would need to be installed. I used Homebrew to install pipex, but if you're on another system, then I'll leave a link to their page in the description section below with their installation instructions. Uh but once you have that installed, then you can say pipex install rough. Now, speaking of Homebrew, Ruff is actually available through Homebrew as well. But I generally shy away from using Homebrew for Python packages. Uh because Homebrew's Python package installations sometimes don't handle dependencies as cleanly as Python specific tools. Uh so you could use Brew Install Ruff for this also, but like I said, I tend to shy away from this. My preferred method and the one that I'll be using in this video is to install Rough using UV. And uh as I mentioned, I covered UV in the last video and I'll leave a link to that in the description section below. So I installed UV itself using Homebrew. And once UV is installed, then we can install rough as a global tool by saying UV tool install rough. So that's how I'm going to do it here in this video. But whichever method you choose, uh, you should be able to check that the installation worked just by saying rough d- version. And we can see that, let me make this a little larger down here. We can see that uh, we have this new rough version here. So now that we have rough installed, let's take a look at how to use this from the command line. And like I said earlier, we'll be seeing how to integrate this into VS Code as well, so that it highlights and formats our code automatically. But understanding the command line basics first is really helpful for understanding what the VS code extension is doing uh behind the scenes. Okay. So first I've got a sample Python file open up here and I currently have my usual VS code linting and formatting turned off so that we can see this from the command line first. So you might see a few issues already just by looking at this code. Um but if I run the code then it should work fine. So, let me run this. And we can see down here that we're just printing out this greeting for query. We're calculating these averages here. And we're parsing a uh JSON file here. And these are those functions there. So, the code runs fine and there's no glaring issues. Uh, but let's see what rough has to say about it here. So, I'm going to go back to my terminal and let's use rough to check this. So to do this we can say rough check and then the name of the file and this is main. py here. So if I run that then we can see that it found six errors here and that five of these are fixable with the d-fix option. It's finding six

### Segment 2 (05:00 - 10:00) [5:00]

mistakes right now but this is with Rough's default configuration and we'll see how to check uh for even more errors in just a bit. And let me make this terminal just a little bit larger here. Once again, um, now if I wanted to check multiple files at the same time, then I could run a check on the entire directory. Uh, so for example, to check the entire current directory, then I could just pass that in as a terminal command there. And this is the only f uh Python file that I have in this directory here. So it's just finding those six errors once again. So let me clear that out. So when we run this, let's go through exactly what it's showing us here. So it's going to point out an exact error and line number and also give us an error code. So let's scroll through and look at some of these here. So we have just six total here. Um we can see that one of these is multiple imports on one line, which is line one up here. Um another one is CIS is imported but unused. um time imported but unused. A lot of imports that we're not using here. So, same with datetime, same with random. And then we have one here that is do not use bare except. Now, a lot of these errors probably make sense, but some of them might not. And I've found this is actually a really good way to learn Python as well because as you're writing code and RF is catching mistakes, their documentation is very good at breaking down why certain things are mistakes and give you examples of how you can improve or fix your code. So for example, this last error here in our terminal, it's error E722. Do not use a bare except. So let's say that you don't know what that means or why you wouldn't use a bare exception there. And let's scroll down to that actual line here. So this is what it is catching right here. So let's actually copy this error code here. And I'm going to pull up their documentation in the browser and let's search this in their rule sets and pull up uh this code. And I'm going to be sure to leave a link to this documentation in the description section below. It's super useful. Uh but now if I read through this page, it breaks down exactly why this is bad and why we shouldn't do this. So we can see that this was derived from the pi code style llinter. Um what it does it checks for bare except uh catches in try except statements. Why is this bad? A bare except catches base exception which includes keyboard interrupt, system uh system exit exception and others. Catching a base exception can make it hard to interrupt the program example with control C and can disguise other problems. Then they give you an example of what this looks like. This looks pretty similar to our code. We're just doing a try except it's saying use instead to do a more specific exception when we catch this. And if we actually need to catch an unknown error, uh use exception which will catch regular problems but not important uh system exceptions. So now let's go back to our code and see if we can fix this. So one of the coolest features about rough is that it can automatically fix a lot of the errors on its own. Uh you can see that it says five of them are fixable down here with this d-fix option. And it's careful to only automatically fix issues that won't break the functionality of your code. So if I wanted it to try to fix our code, then I could say, let's clear our terminal here. I'm just going to do a rough check and then add in that fix option. And I'm going to keep running this on the entire directory I have here, even though that's only one Python file. So I'm going to run this. And if I run that, we can see that it says that it found six errors, fixed five of them, and that one remains. And it displays the error that still remains here, which is that bare except. Uh, and if we look at our code now, then we can see that this is now cleaned up a lot. It took out all of those unused imports and some other issues that it saw. Now, you might not want to fix the code automatically without knowing exactly what it's going to do. So, let me undo those changes really quick. So, I hit control Z or command Z on a Mac. And I undid those changes. And let me save those. And now, let's go back and see how we can see the changes that it's going to make when it automatically fixes this. To do this, we can add in the dash diff option. And if I run this now, then this is

### Segment 3 (10:00 - 15:00) [10:00]

going to give us exactly what it would change without um actually modifying the file. It displays this almost like a get diff would. So we can see here it's taking out all these unused imports here. And uh that was it. Actually, I forgot that uh the only problems that we had were import problems there, but I was fine with those changes that it made. Uh so, I'm going to rerun this command here, take out that d- diff, and just rerun that with the fix. And it makes those changes and then returns the one error that we still have here. And again, I'm going to make this a little larger so we can see everything. So, we do still have this one error here that it didn't fix automatically. And in the documentation, it told us how we can fix this, but I'm going to leave that there for just a bit while we look at some more of what we can do with rough. So, rough also includes a black compatible code formatter. To use this, you can use the format command instead of the check command. So, I'm going to rerun this here and instead of check, I'm going to say format and run that. And after I run that, you can see that our script has been reformatted to follow standard conventions and looks real nice with the proper line spacing, whites space, and things like that. Now, just a quick tip on workflow. You're generally going to want to run a rough check fix first to fix uh the linting issues and then run rough format afterwards. Uh that way the fixes don't mess up any of the formatting. Now if you have your terminal open while you're working on a script then you can actually have rough check for errors in real time. So we can do that with the d-watch option. So if I do this instead of fix if I say watch now it's going to watch for errors here. So if I go up into my script and I import something that I'm not using in the script. So, if I do like an import cis and save that, then as soon as I save that, we can see down here that it's watching and now says, hey, you imported something that you're not using. And to have it stop watching that file, we can just exit out with controll C. And now I'll clear that. Okay. So, real quick, since we already fixed that those import issues, I'm just going to go ahead and undo when I added that in. And let me redo this uh rough check here without the watch uh just to make sure we still have our one error. And we do. Okay. So now let's talk about how to configure Rough because I use Rough for so much more than what we've seen so far. The defaults that come with Rough are great and non-controversial, but there are over 800 built-in rules that we could be checking for in order to find errors in our code. Now, I don't use them all, but I do use a lot. And I find that there are so many useful ones outside of the default rule set. Uh so there are a few different ways to configure rough. We can configure it globally to apply to all of our projects. Uh locally to apply to individual projects or a mix of both where the local configuration overrides the global configuration if you do that. So first let's look at setting this up locally in our project. We can use a pi project. totml toml file which is the standard configuration file for modern Python projects. You can also use a roughl file if you'd like. Uh rough looks for these files in the current directory and parent directories. Uh I'm going to use the pi project. totml file for now and we'll look at a rough. l file in just a bit. Uh if you don't have a piprototl file, you can uh create one of those in your project directory. But once you have one of those, we can open it up. And I have one already created here. So let me open that and close down the sidebar there. And make this a little smaller so we can see. Now the piro. comtoml file can configure many different Python tools. So rough settings need to be nested under a tool. Section uh to avoid clashes. So this is going to be tool. ruff. Okay. And within here, we can configure rough a bit. Uh, so the main thing you'll likely want to do is to extend on the default rules that rough enforces. To do this, we can say lint dot extend select. And that's extend- select. Sorry. And for now, I'll just set that to empty. And now we can pass in rule codes that we want Ruff to enforce. So, for example, I know Ruff has one rule that enforces the use of pathlib over using uh the built-in open function, and that rule is path pth all capital

### Segment 4 (15:00 - 20:00) [15:00]

letters. So, I like using path liib when I can for a lot of reasons. So, that's why I'm going to enforce this in my code. If you don't know the advantages of using pathlib, then I do have a video on that if you're interested. So, I'll leave a link to that video in the description section below as well. Uh but now that we have this rule being added uh to what we're watching for, let's save this and rerun rough check on our script. So I've got this pi project. comtotl file saved. I'm going to go back to our script here. And now let's rerun our rough check. So I will rerun this. And now we can see that we're getting two errors. So let me scroll up to this other error that we're getting here. And we can see that it's PTH123 open should be replaced by path. open. So now that we've added these PTH rules for rough to watch, now it's enforcing that on our codebase. And now you might be thinking, okay, that's cool, but how did you know uh the rule code to enforce uh that? How did I know that this was PTH here? So I get all of these rules from the documentation that we saw earlier. So, if I pull the documentation back up here, let me click on their rules section over here, and I'll scroll through these a bit. Um, so we can see that also in their sidebar, uh, they have a lot of these listed here as well. Um, but if I scroll through, we can see that, uh, they have a fast API section. They have some flake 8, flake 8 annotations, uh some a section for async and all kinds of different things here. Now, I make the text on my browser a little larger for the videos here. Uh so it makes it hard to see what all is available over here in um the sidebar. Uh but if I make this a little smaller, you can see that we have a lot over here. And if I reload this, I think yeah, the sidebar was broken from where I'd done a bunch of resizing and stuff. So you can see that we get a better overview over here in the sidebar of all these different rules. So now let me make that larger again so that we can read. Okay. So what I did personally was I browsed through this list. I read the descriptions for the different sections here and gradually added rules to my extend select list if they seemed useful and matched my coding style. Now, that might be a bit more work than you want to do just to set up your uh the rules for your lender. Uh so, one strategy that you can use to discover rules is to just select all of them. And we can do that with just by adding all here instead of individual rules. So, I'm going to save that. Uh but I've got to warn you, Rough comes with a lot of built-in rules. We just saw uh a small section of them over on in their documentation and some of them even conflict with each other. So for example, there are multiple different ways to enforce dock string formats depending on your coding preference, but Rough will tell you when rules conflict. So another thing is that you're likely going to get a lot of errors and suggestions if you're using all of the rules. Uh so just on my super short script here, uh let me run a check here with all of the rules selected. So if I now do a rough check on this and run it, then we can see that just with this short little 30 line script, we're getting 15 errors. And some of these might be things that you don't necessarily care about. Uh so for example, one of the rules that it's enforcing here is that we shouldn't use print statements and that we should remove print statements. Now I use print statements all the time because it's easiest way it's the easiest way for me to teach uh in these videos. Uh but not having print statements in production code is probably a good idea. Uh but let's say that you didn't care about print statements in your code. Well, if that's the case, then another thing that we can do is ignore certain error codes. Uh, so I could copy this T201 code here, go back to my piprottoml file, and now I can do a lint. Section, and I will set this equal to just that one code that we just copied. I will save that. And now I'll go back to my terminal here. I will rerun that check. And now we can see that we're getting 12 errors. And the bottom one is no longer that one about using print statements. And since we're getting 12 errors instead of 15, that means that we must have had three print statements getting flagged in that script. Uh so that's one option that you can use if you want to discover

### Segment 5 (20:00 - 25:00) [20:00]

different codes that you may or not may not have known about. Uh, but the method that I personally used was adding in individual codes as I went through their documentation and I added everything that I wanted into my global rough configuration so that it used those same checks on all of my projects without me needing to specify them in my pi project. toml file like we've done here so far. So let's look at how we can create a global rough config and we can see what mine looks like as well. Uh but first I'm going to delete my project configurations here so that we can be sure that the global one is working. So I'm going to go to the project tol file and just remove all of those uh that we' added in there. Okay. And again just to make sure that worked rerun that check. We're back to our one error that we had before. So that's working. Okay. So for a global configuration, your operating system is going to determine where you create this. Now I'm on a Mac, so I created this at in my home folder and then within configrl file here. So let me go ahead and open this up to make sure that is the correct location. And yes, I do trust and okay. So, yep, this is my rough configuration file here, my global one. Now, if you're on Windows, I don't know that location off the top of my head, but I'll be sure to put it up on the screen here now. And I'll also do the location for Linux as well. I think it's the same as what it is for Mac. And I'll give those a second to fade away um and for you to see those. Let me go ahead and close this. And now we can take a look at my global rough configuration file. So currently this is all commented out because I didn't want my personal rule set interfering with the beginning of the video. But now I'm going to go ahead and uncomment this. So I'll uncomment all this and save it. And I actually had it open over here as well. So I'm going to close that one. So now let's go ahead and look through this. And I've got this fairly well commented. And I'll also have a link to this configuration in the description section below if anyone would like this as a starting point. So at the top here, I commented what the default rule set was for rough um so that I had that as a reference. And then if I scroll through, we can see that there are some rules that I have uncommented because sometimes I want to flag annotations, sometimes I don't. Um and sometimes I don't want print statements and sometimes I do. So, I have those options there if I want them. And then down here towards the bottom, I also have some that I am ignoring. Uh like I don't like it telling me when my lines are too long. Um things about the dock strings and stuff like that. Um and you can see that I also have uh comments here for what each of these rules does just so that I can tell at a glance without having to go to their documentation. Okay. So now that I have my global config saved here and all of that is uncommented, now let's go back to our script and let's rerun our uh check again to see what we get. So I'm going to do a rough check now. And now using my personal global rough configuration, we can see that we're getting uh five errors here now. And one of those is fixable with the autofix feature. Now, since we can't autofix a lot of the ones we're getting here, this is where integrating Rough with VS Code becomes extremely useful. And this is probably how most of you will want to use Rough day-to-day. I could have just started off the video showing you how to integrate Rough into VS Code, but I feel like you're not going to get the most out of uh using this unless you understand what it's doing in the background. So now that we've done that a bit, now let's see how to get this integrated with VS Code so that it shows these errors within our editor automatically without us running this rough check command every time. Now one big benefit of using Rough in VS Code is that it allows you to remove multiple other extensions like black eyes sort pilent and things like that since Rough can handle all of those for you. So, if you have those extensions installed, then you should be able to safely remove them after you get Rough set up. So, first of all, we're going to install the Rough extension. So, I'm going to open up my extensions here. Let me make this a little larger. And I've actually already come in here and deleted a lot of uh what I was using before, like black and sort and things like that. So

### Segment 6 (25:00 - 30:00) [25:00]

you can see I no longer have those in my extensions since I'm using Rough. So, I'm going to do a search here for Rough. I uninstalled it before this video. So, now I'm going to reinstall it here. And like any other extension, we're going to see a readme page pop up explaining how we can set this up. And there's some good information in here. Uh, I'll show you the same information in my settings. So, we can actually just go ahead and close this, but you'd likely want to go ahead and read through that. And let me go ahead and close that sidebar. And I'm going to open up my settings here. And I already have these ready to uncomment here in my settings. json file. So, let me scroll down to my Python section and uncomment these and then I will explain what they do. Oops. And I also wanted to include these two as well here. So let me go ahead and save that. So now let me go ahead and explain these here. So this editordefault formatterater with this charlie uh r marsh. ruff this sets rough as the default formatter for python files. The format on save applies formatting every time you save a file. Uh this source. fixall fix all will automatically apply all the possible fixes on save. Now, now that I'm thinking about it, I'm actually going to leave this commented out uh because I like to see the errors without them being fixed automatically. That way, I can learn from any errors or coding convention mistakes that I make, but you can enable that if you'd like. Um, and for source. organize imports here, this sorts your imports on save. And these are the same settings that we would have seen in the readme file uh if we had read through that. So I also have my VS Code settings available on my GitHub in the dot files repo if anyone is interested in seeing all of my VS Code settings that I've shown here. Now these last two here for inlay hints uh these aren't rough specific but they're helping me fix uh some of the rough warnings by suggesting type hints. Okay, so with these uncommented, we should have rough working directly in our editor. And hopefully I don't have to uh restart the editor and it should still be applying my global config that I showed earlier. So if I close down my settings here and reopen our terminal here, then first let's see if it's auto formatting. If I just add in a couple of unneeded lines here, if I then save that, we can see that it automatically formatted for us. So, that's good. And we're also getting a lot of highlighted code here now. So, we can see here that sum is highlighted. Uh, open except. So, if I open up this problems tab, then that's going to show us what all of those highlights are for. So if I open that up. So now we can see that we have this immediate feedback listing those five errors that we saw in the terminal before. Now one of the best things about this in VS Code is that I can just commandclick uh I'm not sure what that is on Windows, maybe control-click uh any of these codes and it's automatically going to take me to that documentation page directly in the browser. So if I choose one of these like um this one here, I'm going to trust this and open it up. Then we can see that it automatically opens up that code uh so that we can see what the problem is. So this is saying that it checks for variable and function assignments that use the same name as built-ins. So that's what this is here. I was calling this variable sum and it doesn't like that because there is a sum built-in that we are overwriting. So, I find the ability to just be able to click on these and go directly to the documentation. I think that's super useful. And I've learned a lot from these already. Things that um I didn't already know just from my normal coding and applying um different rule sets uh that I've noticed that uh I have some bad habits that these have pointed out to me. So now, even on this super small script that ran perfectly fine at the beginning of the video without anything super noticeable, now we can go through here and start improving our code. Now, I ran a poll on my community tab about a week ago asking if I should start using type hints in my tutorials, and most of you said yes. And Ruff actually has a rule set completely devoted to typins. So if I wanted to apply that, then I could go back to my uh global configuration file here, this one for annotations, I could uncomment that and

### Segment 7 (30:00 - 35:00) [30:00]

save it. Now, if we go back to the script here, I may need to uh restart VS Code for these to take effect. Let me go ahead and just restart this really quick. Pull it back up. And now we can see that we have 11. And a lot of these are for type annotations. So to fix these, I could go through and hover over each of these and fix them. Uh or if you have something like co-pilot installed, then I could ask C-pilot to fix it for me. And whenever you have co-pilot fix something that uh Ruff says is a problem, then Ruff is going to give that context to the AI and that's going to make it much more likely that it's going to be done correctly. So it even helps out things like co-pilot. But honestly, I think that the rough error codes offer so much detail and examples that using AI for fixing these things is a bit much. Uh so for example, um if I look at the someone here, that's shadowing a Python built-in. So since that I know that that's a built-in, I could instead use something like total instead of sum. I save that and that goes away. Now, for anybody who is a little OCD out there, uh, I'll go ahead and clean up the rest of these things that Ruff brought to our attention so that we don't have any more errors. I know that would bug me if I watched a video and somebody left all of these errors here. Um, so I'm going to go in and fix these really quick and I'll just skip ahead a bit in the video so that you don't have to watch me fix a lot of the same issues and add in type annotations. Okay, so I've gone through and I've fixed those errors. Uh I've added type hinting where needed according to the rules that I've put in place. Um I am now using path lib instead of the built-in open. Um I've also imported pathlib up here. Um I'm also using a more specific exception catch here when we try to access our file. Um, so now we're passing uh all of our rough checks. And I don't even need to test that in the terminal anymore now that we have this set up in our editor. But if we wanted to see what that looked like, then I will go ahead and open up my terminal here. Uh, just so we can see all checks passed is what it looks like in the terminal. Uh, if we pass all of those there within the terminal. So, even though I had this very simple script that seemingly ran fine when we first started, there were a bunch of issues that Ruff pointed out that either improved our code or got it more in line with uh our coding style, my coding style specifically. Uh, like I said, I've been using Rough personally for some time now, and I like it a lot more than the tools that I was using. So, first of all, it's an all-in-one tool, so I don't have to install my formatterers and liners separately. And not only that, but it manages to be a lot faster than a lot of those previous tools as well. And I love the amount of control that I have over specifying the exact rules and issues that I wanted to catch. So, I definitely recommend trying it if you haven't yet. Now, one side note that I wrote down to mention at the end here is about type hinting. So, I mentioned that Ruff does have some rules to enforce type hinting, but I don't want you to confuse that with a type checker. A type checker is something that analyzes your code and lets you know if you're actually using the wrong data types in different places, like passing in a string where an integer is expected. So a popular type checker is my pi and you can use that alongside rough to keep even better track of your code. I use both of those together and they work great. Uh but type checking is something Ruff might take on in the future. Uh so maybe someday that will be another tool that Rough uh wraps under its belt. And I've actually changed up my workflow a good bit from what it used to be. So, I think sometime soon I'm going to do an updated overview of my complete VS Code setup for Python so that everyone can see the tools and extensions that I'm currently using and how they all work together. So, be sure to subscribe if you want to see that video when it comes out. But with that said, I think that's going to do it for this video. Hopefully now you have a good idea for how to set up and use Rust for your Python projects. Uh there's plenty that you can use it for that we didn't cover in this video. So for example, you can set it up with pre-commit hooks so that you can make sure all of your code committed to your repositories is consistently linted and formatted. But I think this was a good

### Segment 8 (35:00 - 35:00) [35:00]

starting point in seeing what it's capable of and why you'd want to use it over other tools. But if anyone has any questions about what we covered in this video, then feel free to ask in the comment section below and I'll do my best to answer those. And if you enjoyed these tutorials and would like to support them, then there are several ways you can do that. The easiest way is to simply like the video and give it a thumbs up. Also, it's a huge help to share these videos with anyone who you think would find them useful. And if you have the means, you can contribute through Patreon or YouTube, and there are links to those pages in the description section below. Be sure to subscribe for future videos, and thank you all for watching.
