The Python Oracle

Python3 project remove __pycache__ folders and .pyc files

--------------------------------------------------
Hire the world's top talent on demand or became one of them at Toptal: https://topt.al/25cXVn
and get $2,000 discount on your first invoice
--------------------------------------------------

Music by Eric Matyas
https://www.soundimage.org
Track title: Forest of Spells Looping

--

Chapters
00:00 Python3 Project Remove __pycache__ Folders And .Pyc Files
00:29 Accepted Answer Score 127
00:46 Answer 2 Score 462
01:05 Answer 3 Score 192
03:14 Answer 4 Score 64
03:57 Thank you

--

Full question
https://stackoverflow.com/questions/2899...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python #python3x #python34 #deletefile

#avk47



ANSWER 1

Score 462


You can do it manually with the next command:

find . | grep -E "(/__pycache__$|\.pyc$|\.pyo$)" | xargs rm -rf

This will remove all .pyc and .pyo files as well as __pycache__ directories recursively starting from the current directory.




ANSWER 2

Score 192


macOS & Linux

BSD's find implementation on macOS is different from GNU find - this is compatible with both BSD and GNU find. Start with a globbing implementation, using -name and the -o for or - Put this function in your .bashrc file:

pyclean () {
    find . -type f -name '*.py[co]' -delete -o -type d -name __pycache__ -delete
}

Then cd to the directory you want to recursively clean, and type pyclean.

GNU find-only

This is a GNU find, only (i.e. Linux) solution, but I feel it's a little nicer with the regex:

pyclean () {
    find . -regex '^.*\(__pycache__\|\.py[co]\)$' -delete
}

Any platform, using Python 3

On Windows, you probably don't even have find. You do, however, probably have Python 3, which starting in 3.4 has the convenient pathlib module:

python3 -Bc "import pathlib; [p.unlink() for p in pathlib.Path('.').rglob('*.py[co]')]"
python3 -Bc "import pathlib; [p.rmdir() for p in pathlib.Path('.').rglob('__pycache__')]"

The -B flag tells Python not to write .pyc files. (See also the PYTHONDONTWRITEBYTECODE environment variable.)

The above abuses list comprehensions for looping, but when using python -c, style is rather a secondary concern. Alternatively we could abuse (for example) __import__:

python3 -Bc "for p in __import__('pathlib').Path('.').rglob('*.py[co]'): p.unlink()"
python3 -Bc "for p in __import__('pathlib').Path('.').rglob('__pycache__'): p.rmdir()"

Critique of an answer

The top answer used to say:

find . | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm -rf

This would seem to be less efficient because it uses three processes. find takes a regular expression, so we don't need a separate invocation of grep. Similarly, it has -delete, so we don't need a separate invocation of rm —and contrary to a comment here, it will delete non-empty directories so long as they get emptied by virtue of the regular expression match.

From the xargs man page:

find /tmp -depth -name core -type f -delete

Find files named core in or below the directory /tmp and delete them, but more efficiently than in the previous example (because we avoid the need to use fork(2) and exec(2) to launch rm and we don't need the extra xargs process).




ACCEPTED ANSWER

Score 127


I found the answer myself when I mistyped pyclean as pycclean:

No command 'pycclean' found, did you mean:
  Command 'py3clean' from package 'python3-minimal' (main)
  Command 'pyclean' from package 'python-minimal' (main)
  pycclean: command not found

Running py3clean . cleaned it up very nicely.




ANSWER 4

Score 64


Since this is a Python 3 project, you only need to delete __pycache__ directories -- all .pyc/.pyo files are inside them.

find . -type d -name __pycache__ -exec rm -r {} \+

(Note: using -delete instead of -exec rm -r {} \+ won't work because it can't delete non-empty directories)


Alternatively, if you're doing this in a directory that's under revision control, you can tell the RCS to ignore __pycache__ directories recursively. Then, at the required moment, just clean up all the ignored files. This will likely be more convenient because there'll probably be more to clean up than just __pycache__.