큰 파이썬 프로젝트에서 죽은 코드 찾기
나는 본 적이 사용하지 않는 기능 파이썬 코드에서 찾을 수 있습니까? 하지만 그건 정말 오래되었고 제 질문에 답하지 못했습니다.
여러 진입 점 스크립트에서 공유하는 여러 라이브러리가있는 대규모 Python 프로젝트가 있습니다. 이 프로젝트는 많은 저자들과 함께 수년 동안 축적되어 왔으므로 죽은 코드가 많이 있습니다. 당신은 훈련을 알고 있습니다.
죽은 코드를 모두 찾는 것은 결정할 수 없다는 것을 알고 있습니다. 필요한 것은 어디에도 호출되지 않는 모든 기능을 찾을 수있는 도구입니다. 함수 이름의 문자열을 기반으로 함수를 호출하는 것은 멋진 일이 아니므로 병리학적인 것에 대해 걱정하지 않습니다.
방금 pylint를 설치했지만 파일 기반으로 보이며 파일 간 종속성 또는 기능 종속성에 많은 관심을 기울이지 않습니다.
분명히, 모든 파일에서 def를 grep하고, 모든 함수 이름을 가져오고, 각 함수 이름에 대해 grep을 수행 할 수 있습니다. 나는 이미 저 밖에있는 것보다 조금 더 똑똑한 것이 있기를 바라고 있습니다.
ETA : 완벽한 것을 기대하거나 원하지 않습니다. 나는 내 멈춤 문제에 대한 증거를 누구와 마찬가지로 알고 있습니다. 실제로 코드를 실행하여 근사화하려고 시도하는 것은 너무 오래 걸립니다. 나는 단지 구문 론적으로 코드를 통과하고 "이 함수는 확실히 사용됩니다.이 함수는 사용될 수 있습니다.이 함수는 확실히 사용되지 않습니다. 다른 사람도 그것이 존재한다는 것을 알지 못하는 것 같습니다!"라고 말하는 것을 원합니다. 그리고 처음 두 범주는 중요하지 않습니다.
독수리 를 시험해보고 싶을 수도 있습니다 . Python의 동적 특성으로 인해 모든 것을 잡을 수는 없지만 coverage.py와 같은 전체 테스트 스위트가 필요하지 않고 다른 것들이 작동 할 필요없이 꽤 많이 잡습니다.
Ned Batchelder 의 coverage.py를 실행 해보십시오 .
Coverage.py는 Python 프로그램의 코드 커버리지를 측정하는 도구입니다. 프로그램을 모니터링하여 코드의 어떤 부분이 실행되었는지 확인한 다음 소스를 분석하여 실행되었을 수 있지만 실행되지 않은 코드를 식별합니다.
코드가 멋진 작업을 수행하지 않더라도 코드를 실행하지 않고 호출되는 함수와 메서드를 결정하는 것은 매우 어렵습니다. 일반 함수 호출은 감지하기 쉽지만 메서드 호출은 정말 어렵습니다. 간단한 예 :
class A(object):
def f(self):
pass
class B(A):
def f(self):
pass
a = []
a.append(A())
a.append(B())
a[1].f()
여기서는 멋진 일이 없지만 A.f()
또는 B.f()
호출 되는지 여부를 결정하려는 스크립트는 실제로 코드를 실행하지 않고는 수행하기가 다소 어려울 것입니다.
위의 코드는 유용하지 않지만 실제 코드에 나타나는 패턴, 즉 컨테이너에 인스턴스를 넣는 패턴을 확실히 사용합니다. 실제 코드는 일반적으로 피클 링 및 언 피클 링, 계층 적 데이터 구조, 조건문 등 훨씬 더 복잡한 작업을 수행합니다.
이전에 언급했듯이 양식의 일반 함수 호출 만 감지합니다.
function(...)
또는
module.function(...)
다소 쉬울 것입니다. ast
모듈을 사용 하여 소스 파일을 구문 분석 할 수 있습니다. 모든 가져 오기와 다른 모듈을 가져 오는 데 사용되는 이름을 기록해야합니다. 또한 최상위 수준 함수 정의와 이러한 함수 내부의 호출을 추적해야합니다. 그러면 종속성 그래프가 제공되며 NetworkX 를 사용 하여이 그래프의 연결된 구성 요소를 감지 할 수 있습니다 .
다소 복잡하게 들릴 수 있지만 100 줄 미만의 코드로 수행 할 수 있습니다. 불행히도 거의 모든 주요 Python 프로젝트는 클래스와 메서드를 사용하므로 별 도움이되지 않습니다.
적어도 잠정적으로 사용하고있는 해결책은 다음과 같습니다.
grep 'def ' *.py > defs
# ...
# edit defs so that it just contains the function names
# ...
for f in `cat defs` do
cat $f >> defCounts
cat *.py | grep -c $f >> defCounts
echo >> defCounts
done
그런 다음 참조가 거의없는 개별 함수를 살펴 봅니다 (<3 말).
추악하고 대략적인 대답 만 제공하지만 시작하기에 충분하다고 생각합니다. 여러분 모두의 생각은 무엇입니까?
다음 줄을 사용하면 분명히 속성, 함수 호출, 데코레이터 또는 반환 값으로 사용되지 않는 모든 함수 정의를 나열 할 수 있습니다. 그래서 그것은 대략 당신이 찾고있는 것입니다. 완벽하지 않고 느리지 만 오 탐지가 전혀 없습니다. (리눅스에서는으로 교체 ack
해야합니다 ack-grep
)
for f in $(ack --python --ignore-dir tests -h --noheading "def ([^_][^(]*).*\):\s*$" --output '$1' | sort| uniq); do c=$(ack --python -ch "^\s*(|[^#].*)(@|return\s+|\S*\.|.*=\s*|)"'(?<!def\s)'"$f\b"); [ $c == 0 ] && (echo -n "$f: "; ack --python --noheading "$f\b"); done
If you have your code covered with a lot of tests (it is quite useful at all), run them with code-coverage plugin and you can see unused code then .)
IMO that could be achieved pretty quickly with a simple pylint plugin that :
- remember each analysed function / method (/ class ?) in a S1 set
- track each called function / method (/ class ?) in a S2 set
- display S1 - S2 in a report
Then you would have to call pylint on all your code base to get something that make sense. Of course as said this would need to checked, as there may have been inference failures or such that would introduce false positive. Anyway that would probably greatly reduce the number of grep to be done.
I've not much time to do it myself yet but anyone would find help on the python-projects@logilab.org mailing list.
참고URL : https://stackoverflow.com/questions/9524873/finding-dead-code-in-large-python-project
'program story' 카테고리의 다른 글
java.security.Signature 대 MessageDigest 및 Cipher와 함께 SHA1 및 RSA 사용 (0) | 2020.11.12 |
---|---|
PHP : __ ( 'Some text')는 무엇을합니까? (0) | 2020.11.12 |
x86_64는 전체 레지스터 내용을 덮어 쓰는 rax / eax / ax / al을 등록합니다. (0) | 2020.11.12 |
액세스 토큰 대 액세스 토큰 비밀 및 소비자 키 대 소비자 비밀이란 무엇입니까? (0) | 2020.11.12 |
MySQL Workbench (6.3.9)가 MacOS High Sierra와 호환되지 않습니까? (0) | 2020.11.12 |