[Python] python fomatter: ruff์ black
๐ต ํ์ด์ฌ ํฌ๋งทํ
์์ ์ ์กฐ๊ต๋ฅผ ํ ๋ ์ด ์ฌ๋์ด ์ฝ๋๋ฅผ ์ข ํ๋ ์ฌ๋์ธ์ง ์๋์ง ์๋ ๋ฐฉ๋ฒ์ ์ฝ๋์ ํฌ๋งท์ ์งํค๋์ง ๋ณด๋ ๊ฒ์ด์๋ค. ๊ทธ๋ฐ๋ฐ ์์ฆ์ ์๋๊ฐ ์ข์์ง ๊ฒ์ธ์ง VScode์๋ ํฌ๋งคํฐ๊ฐ ์๋์ผ๋ก ํฌ๋งทํ ์ ํด์ค๋คโฆ ๊ทธ๋์ ๋๋ ๋ญ ์ํด์ ํฌ๋งทํ ๊ณต๋ถํ๋ฉด์ ์ผ์ผ์ด ๊ณ ์น๊ณ ์์ ์์๋ ๊ฒ์ธ๊ฐใ
์๋ฌดํผ VScode ์ฌ์ฉ์๊ฐ ํ์ด์ฌ ์ฝ๋ ์คํ์ผ์ ๊น๋ํ๊ฒ ์ ์งํ๊ณ ์ถ๋ค๋ฉด ์ฝ๋ ํฌ๋งคํฐ(formatter)๋ ํ์ ์ต์คํ ์ ์ด๋ค.
์ต๊ทผ์ ruff
๊ฐ ์์ฒญ๋๊ฒ ํซํด์ง๋ฉด์, ๊ธฐ์กด์ black
๊ณผ ๊ฐ์ด ์ฐ๋ฉด ๊ฟ์ด๋ผ๋ ์ ๋ณด๋ฅผ ์ป์ด์
์ด๋ฒ ๊ธ์์ VSCode ๊ธฐ์ค์ผ๋ก ์ถ์ฒํ๋ ํฌ๋งคํฐ ์กฐํฉ๊ณผ ์ค์ ๋ฒ์ ๊ฐ๋จํ ์ ๋ฆฌํด๋ณด์๋ค.
โช ์ฃผ์ ํ์ด์ฌ ํฌ๋งคํฐ ๋น๊ต
Formatter | ์ฃผ์ ํน์ง | ์ฅ์ | ๋จ์ |
---|---|---|---|
black | ์ฝ๋ ์คํ์ผ์ ์๊ฒฉํ๊ฒ ํต์ผํด์ค | - ์ค์ ๊ฑฐ์ ์์ด ๊น๋ํ ์คํ์ผ - ์ผ๊ด์ฑ ์ต๊ณ | - ๋๋ฌด ๊ณ ์ ๋ ์คํ์ผ์ด๋ผ ์ปค์คํฐ๋ง์ด์ง ์ด๋ ค์ |
ruff | ํฌ๋งคํ
+ ๋ฆฐํ
+ ์ฝ๋ ์์ ๊น์ง ํตํฉ Rust๋ก ๊ตฌํ๋์ด ๋งค์ฐ ๋น ๋ฆ | - ์๋ ์ต๊ฐ - flake8, isort, black ๋ฑ ๋์ฒด ๊ฐ๋ฅ - ๊ฑฐ์ ๋ชจ๋ ๋ฆฐํฐ ๋ฃฐ ํฌํจ | - ์์ง ํฌ๋งคํ ๊ธฐ๋ฅ์ black๋งํผ ์์ฑ๋์ง ์์ (2025๋ ๊ธฐ์ค) |
autopep8 | PEP8์ ๋ง์ถฐ ์ฝ๋ ์์ | - ๊ฐ๋ณ๊ณ ๊ฐ๋จ | - ์์ฆ์ ๊ฑฐ์ ์ฌ์ฉ ์ ํจ - ์ปค๋ฎค๋ํฐ ์ง์ ์ฝํจ |
โช ๋ฆฐํฐ(Linter)๋?
๋ฆฐํฐ๋ โ์ฝ๋์ฉ ๋ง์ถค๋ฒ & ๋ฌธ๋ฒ ๊ฒ์ฌ๊ธฐโ
- ๋ฆฐํฐ๊ฐ โ์ด ๋ฌธ์ฅ์ ์ฃผ์ด์ ์์ ์ด๊ฐ ๋ง์ง ์๊ณ , ์ ๋จ์ด๋ ์คํ๊ฐ ๋ฌ๋ค์.โ ๋ผ๊ณ ์๋ ค์ฃผ๋ ๊น๊นํ ๊ต์ ์ ๋ฌธ๊ฐ๋ผ๋ฉด, ํฌ๋งคํฐ๋ โ๊ธ์ ๊ฐ๊ฒฉ, ์ค ๋ฐ๊ฟ, ๋ค์ฌ์ฐ๊ธฐ๋ฅผ ๊ท์น์ ๋ง๊ฒ ์๋์ผ๋ก ๋ง์ถฐ์ฃผ๋ ํธ์ง ๋์์ด๋โ ๊ฐ์ ๋๋.
1
2
3
4
5
import os, sys # 1. ํ ์ค์ ์ฌ๋ฌ ๋ชจ๋ import
def myFunction(name): # 2. ํจ์ ์ด๋ฆ์ด snake_case๊ฐ ์๋
unused_variable = "hello" # 3. ์ฌ์ฉ๋์ง ์๋ ๋ณ์
if name == "chris":
return "Hello Chris" # 4. ๋ค์ฌ์ฐ๊ธฐ๊ฐ 2์นธ์ (PEP 8์ 4์นธ ๊ถ์ฅ)
1): ํ ์ค์ ์ฌ๋ฌ ๋ชจ๋์ importํ๋ ๊ฑด ์ข์ง ์์. (E401) 2): ํจ์ ์ด๋ฆ์ my_function์ฒ๋ผ snake_case๋ก ์จ์ผ ํจ. (N802) 3): unused_variable์ด ์ ์ธ๋์ง๋ง ์ฌ์ฉ๋์ง ์์. (F841) 4): ๋ค์ฌ์ฐ๊ธฐ๊ฐ 4์นธ์ด ์๋. (E111)
โช ์ถ์ฒ ์ธํ : Ruff + Black ์กฐํฉ
Ruff๋ ๋น ๋ฅด๊ณ ์ ์ฐํ์ง๋ง ์์ง ํฌ๋งคํ
์์ฑ๋ ์ธก๋ฉด์์๋ black
์ด ๋ ์์ ์ . ๊ทธ๋์ ๋ ๊ฐ๋ฅผ ํจ๊ป ์ฐ๋ ์กฐํฉ์ด ๊ฐ์ฅ ๋๋ฆฌ ์ฐ์ด๊ณ ์์.
1. VSCode ํ์ฅ ์ค์น
ms-python.python
charliermarsh.ruff
(Ruff ํ์ฅ)
2. VSCode settings.json
์ค์
1
2
3
4
5
6
7
8
9
10
{
"python.formatting.provider": "black",
"python.linting.enabled": true,
"python.linting.ruffEnabled": true,
"python.linting.ruffArgs": ["--fix"],
"editor.formatOnSave": true,
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter"
}
}
์ด ์ค์ ์ ์ ์ฅ ์ black์ผ๋ก ํฌ๋งคํ ๋๊ณ , ruff๋ ์๋์ผ๋ก ์ฝ๋ ๋ฆฐํธ ๋ฐ ์์ (โfix)๊น์ง ์ฒ๋ฆฌํด์ค.
โช ๋์ ์์ ์ฝ๋: ํฌ๋งคํ ๊ณผ ๋ฆฐํธ ์๋ฌ๊ฐ ์์ธ ์ํ
์๋ ์ฝ๋๋ฅผ ๊ทธ๋๋ก test_formatter.py ๊ฐ์ ํ์ผ๋ก ์ ์ฅํ๋ฉด:
- ๋ค์ฌ์ฐ๊ธฐ ํ๋ฆผ
- import ์์ ์ ๋ง์
- ์ค ๋๋ฌด ๊ธบ
- ๊ดํธ ์คํ์ผ ์ ๋ง์
- ์ฐ์ด๊ณ ์์ง ์์ ๋ณ์ ํฌํจ
1
2
3
4
5
6
7
8
import sys,os
import numpy as np
import pandas as pd
def long_function_name( a,b ):
x = 1+2
unused_var = 42
return a+b+ x + np.sum(np.random.rand(100,100)) + pd.DataFrame({"a":[1,2,3]})
โช ์ ์ฅ ํ ๊ธฐ๋ ํจ๊ณผ: ํฌ๋งคํ ๊ณผ ๋ฆฐํธ ์๋ฌ๊ฐ ์์ธ ์ํ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import os
import sys
import numpy as np
import pandas as pd
def long_function_name(a, b):
x = 1 + 2
return (
a
+ b
+ x
+ np.sum(np.random.rand(100, 100))
+ pd.DataFrame({"a": [1, 2, 3]})
)
๐ต ์ ๋ฆฌ
Black
: ์์ ์ ์ด๊ณ ์ผ๊ด๋ ์คํ์ผ. ๋ณด์์ ์ธ ์ ํ.Ruff
: ๋น ๋ฅด๊ณ ๊ฐ๋ ฅํ ํตํฉ ๋๊ตฌ. ์ต๊ทผ ํธ๋ ๋. ๋จ๋ ์ผ๋ก ์ฐ์ฌ๋ ์ถฉ๋ถํ ๊ฐ๋ ฅํจ
python ํฌ๋งคํ ์ ํตํด์ ์ด์ ์คํธ๋ ์ค ๋ฐ์ง ๋ง๊ณ ์๋ ํฌ๋งทํ ์ ํ์.