Interfaces convenientes são boas e, às vezes, o caminho a percorrer. No entanto, na maioria das vezes uma boa composição é mais importante que a conveniência, já que uma abstração composta nos permite implementar outras funcionalidades (incluindo wrappers de conveniência) sobre ela.
A maneira mais geral para sua função usar arquivos é pegar um identificador de arquivo aberto como parâmetro, já que isso também permite usar identificadores de arquivos que não fazem parte do sistema de arquivos (por exemplo, pipes, sockets,…):
def your_function(open_file):
return do_stuff(open_file)
Se soletrando with open(filename, 'r') as f: result = your_function(f)
for demais para seus usuários, você pode escolher uma das seguintes soluções:
-
your_function
usa um arquivo aberto ou um nome de arquivo como parâmetro. Se for um nome de arquivo, o arquivo é aberto e fechado e as exceções são propagadas. Há um pouco de problema com a ambigüidade aqui, que poderia ser trabalhada usando argumentos nomeados. -
Ofereça um wrapper simples que cuida da abertura do arquivo, por exemplo
def your_function_filename(file): with open(file, 'r') as f: return your_function(f)
Eu geralmente percebo essas funções como inchaço da API, mas se elas fornecem funcionalidade comumente usada, a conveniência ganha é um argumento suficientemente strong.
-
Agrupe a funcionalidade
with open
em outra função composta:def with_file(filename, callback): with open(filename, 'r') as f: return callback(f)
usado como
with_file(name, your_function)
ou em casos mais complicadoswith_file(name, lambda f: some_function(1, 2, f, named=4))