O Python tem uma classificação estável, portanto, desde que o desempenho não seja um problema, a maneira mais simples é classificá-lo pelo campo 2 e depois classificá-lo novamente pelo campo 1.
Isso fornecerá o resultado desejado, o único problema é que, se for uma lista grande (ou você quiser classificá-la com frequência), chamar a classificação duas vezes poderá ser uma sobrecarga inaceitável.
list1 = sorted(csv1, key=operator.itemgetter(2))
list1 = sorted(list1, key=operator.itemgetter(1))
Fazer dessa maneira também facilita lidar com a situação em que você deseja que algumas das colunas sejam classificadas inversamente, basta incluir o parâmetro 'reverse = True' quando necessário.
Caso contrário, você pode passar vários parâmetros para o itemgetter ou criar manualmente uma tupla. Provavelmente será mais rápido, mas tem o problema de não generalizar bem se algumas das colunas quiserem ser classificadas inversamente (as colunas numéricas ainda podem ser revertidas negando-as, mas isso impede que a classificação seja estável).
Portanto, se você não precisar de nenhuma coluna classificada inversamente, vá para vários argumentos para itemgetter, se precisar, e as colunas não são numéricas ou você deseja manter a classificação estável por várias classificações consecutivas.
Editar: para os comentadores que têm problemas para entender como isso responde à pergunta original, aqui está um exemplo que mostra exatamente como a natureza estável da classificação garante que podemos fazer classificações separadas em cada chave e terminar com os dados classificados em vários critérios:
DATA = [
('Jones', 'Jane', 58),
('Smith', 'Anne', 30),
('Jones', 'Fred', 30),
('Smith', 'John', 60),
('Smith', 'Fred', 30),
('Jones', 'Anne', 30),
('Smith', 'Jane', 58),
('Smith', 'Twin2', 3),
('Jones', 'John', 60),
('Smith', 'Twin1', 3),
('Jones', 'Twin1', 3),
('Jones', 'Twin2', 3)
]
# Sort by Surname, Age DESCENDING, Firstname
print("Initial data in random order")
for d in DATA:
print("{:10s} {:10s} {}".format(*d))
print('''
First we sort by first name, after this pass all
Twin1 come before Twin2 and Anne comes before Fred''')
DATA.sort(key=lambda row: row[1])
for d in DATA:
print("{:10s} {:10s} {}".format(*d))
print('''
Second pass: sort by age in descending order.
Note that after this pass rows are sorted by age but
Twin1/Twin2 and Anne/Fred pairs are still in correct
firstname order.''')
DATA.sort(key=lambda row: row[2], reverse=True)
for d in DATA:
print("{:10s} {:10s} {}".format(*d))
print('''
Final pass sorts the Jones from the Smiths.
Within each family members are sorted by age but equal
age members are sorted by first name.
''')
DATA.sort(key=lambda row: row[0])
for d in DATA:
print("{:10s} {:10s} {}".format(*d))
Este é um exemplo executável, mas para salvar as pessoas que o executam, a saída é:
Initial data in random order
Jones Jane 58
Smith Anne 30
Jones Fred 30
Smith John 60
Smith Fred 30
Jones Anne 30
Smith Jane 58
Smith Twin2 3
Jones John 60
Smith Twin1 3
Jones Twin1 3
Jones Twin2 3
First we sort by first name, after this pass all
Twin1 come before Twin2 and Anne comes before Fred
Smith Anne 30
Jones Anne 30
Jones Fred 30
Smith Fred 30
Jones Jane 58
Smith Jane 58
Smith John 60
Jones John 60
Smith Twin1 3
Jones Twin1 3
Smith Twin2 3
Jones Twin2 3
Second pass: sort by age in descending order.
Note that after this pass rows are sorted by age but
Twin1/Twin2 and Anne/Fred pairs are still in correct
firstname order.
Smith John 60
Jones John 60
Jones Jane 58
Smith Jane 58
Smith Anne 30
Jones Anne 30
Jones Fred 30
Smith Fred 30
Smith Twin1 3
Jones Twin1 3
Smith Twin2 3
Jones Twin2 3
Final pass sorts the Jones from the Smiths.
Within each family members are sorted by age but equal
age members are sorted by first name.
Jones John 60
Jones Jane 58
Jones Anne 30
Jones Fred 30
Jones Twin1 3
Jones Twin2 3
Smith John 60
Smith Jane 58
Smith Anne 30
Smith Fred 30
Smith Twin1 3
Smith Twin2 3
Observe em particular como, no segundo passo, o reverse=True
parâmetro mantém os primeiros nomes em ordem, enquanto a simples classificação e a reversão da lista perderiam a ordem desejada para a terceira chave de classificação.