Python stosuje kilka protokołów serializacji (czyli zapisu danych obiekt(u/ów) w strumieniu). Dla wersji języka 2.7*, to będą od 0 do 2 a dla 3.6* 0-4. Domyślna 0, poddaje się otwarciu jako plik tekstowy (czyli w znaku 8-bit nie jest istotny) a wyższe ten bit wykorzystują. Im wyższa wersja protokołu, tym dane bardziej "upchnięte". To że plik jest tekstowy nie oznacza oczywiście że możesz go łatwo zinterpretować otwierając .. notatnikiem. Do tej interpretacji służą metody w pickle. Dlatego pojawiają Ci się w tych plikach takie "buraczki" :-)
Protokoły oraz sposób ich obsługi opisane są tu: https://www.python.org/dev/peps/pep-0307/ oraz tu https://www.python.org/dev/peps/pep-3154/ a implementacja jest w języku C.
Co do shelf to w tle stosuje on jedną z baz danych plikowych z którym Twój python został skompilowany. Rodzaj i znaczenie tych plików opisane jest w danym rodzaju bazy danych. Np. dla *dbm plik *.dat zawiera same dane, *.dir zawiera informacje o kluczach i przesunięciach w pliku *.bak przydaje się do cofnięcia operacji lub zapewnienia atomowości. Ogólnie tych plików nie otwiera się notatnikiem bo są tam dane binarne. Służą do tego metody shelf.