Хммм, как-то я упустил это из виду:
Документ о сортировке python https://docs.python.org/3.5/howto/sorting.html упоминает в последнем разделе "Шансы и конец" функцию locale.strxfrm () (см. * 1006). *) в качестве ключевой функции для сортировки, а locale.strcoll () - в качестве функции сравнения.
Таким образом, следующий измененный код является почти нормальным, за исключением того, что функция сравнения не возвращает напрямую true / false, но это нормально вмой контекст
import subprocess
words = [
"Abd",
"éfg",
"aBd",
"aBd",
"zzz",
"ZZZ",
"efg",
"abd",
"fff",
"sra",
"ssa",
"ssb",
"stb",
"ßaa",
]
val1 = "ßaa"
val2 = "ssb"
with open("tosort", "w") as fout:
for word in words:
fout.write(word + "\n")
os.environ["LC_ALL"] = "en_US.UTF-8"
proc = subprocess.Popen(["sort", "tosort"], stdout=subprocess.PIPE)
sort_en_utf = proc.stdout.read().decode('utf-8').split()
os.environ["LC_ALL"] = "C"
proc = subprocess.Popen(["sort", "tosort"], stdout=subprocess.PIPE)
sort_c = proc.stdout.read().decode('utf-8').split()
locale.setlocale(locale.LC_ALL, "en_US.UTF-8")
sort_py1 = sorted(words, key=lambda v: locale.strxfrm(v))
print("%r < %r = %s , but locale.strcoll(%r, %r) = %s for %s"
% (val1, val2, val1 < val2, val1, val2,
locale.strcoll(val1, val2), locale.getlocale())
)
locale.setlocale(locale.LC_ALL, "C")
sort_py2 = sorted(words, key=lambda v: locale.strxfrm(v))
print("%r < %r = %s , but locale.strcoll(%r, %r) = %s for %s"
% (val1, val2, val1 < val2, val1, val2,
locale.strcoll(val1, val2), locale.getlocale())
)
for row in zip(sort_en_utf, sort_py1, sort_c, sort_py2):
print(" ".join(row))
Вывод будет
'ßaa' < 'ssb' = False , but locale.strcoll('ßaa', 'ssb') = -1 for ('en_US', 'UTF-8')
'ßaa' < 'ssb' = False , but locale.strcoll('ßaa', 'ssb') = 1 for (None, None)
abd abd Abd Abd
aBd aBd ZZZ ZZZ
aBd aBd aBd aBd
Abd Abd aBd aBd
efg efg abd abd
éfg éfg efg efg
fff fff fff fff
sra sra sra sra
ssa ssa ssa ssa
ßaa ßaa ssb ssb
ssb ssb stb stb
stb stb zzz zzz
zzz zzz ßaa ßaa
ZZZ ZZZ éfg éfg