Na minha opinião, o código ficou bastante interessante.
No entanto, se me permite apontar, creio que notei um erro na sua criação de classes.
Como é dito pela própria teoria de POO, classes seriam representações de objetos reais, tais como carros, pessoas, funcionários e etc...
Por outro lado, as ações realizadas por tais classes são representadas pelos métodos. Esses seriam correr, trabalhar, comer...
Logo, com isso em mente, a criação de uma classe "Adiciona" é, no mínimo, pouco intuitivo. Seria muito melhor transformar essa função em um método da classe produto. Você até mesmo chegou a criar a função "adiciona_txt", que poderia ser um método perfeitamente. No entanto, criar uma classe somente para inserir essa função é demais. Seu código ficaria bem mais legível se você adicionasse essa função como método a classe produto e deletasse a classe "Adiciona" completamente.
Classes não deveriam ser verbos. Elas devem ser substantivos. Verbos devem ser sempre métodos.
Passando agora ao seu código, conheço uma prática que pode te auxiliar na construção de loops for de uma forma mais intuitiva. Trata-se da estrutura for/else.
Usando seu exemplo como caso, ao invés de escrever algo como:
# Leitura do arquivo
with open(nome_arquivo, "r") as arquivo_leitura:
adicionar = True
for linha in arquivo_leitura:
if produto_str in linha:
adicionar = False
print(f'Ítem {produto_novo["descricao"]} já existe. ')
if adicionar:
with open(nome_arquivo, "a") as arquivo:
if adicionar:
print(f'Adicionando ítem {produto_novo["descricao"]}. ')
arquivo.write(produto_str + '\n')
Você poderia transformar para algo como:
# Leitura do arquivo
with open(nome_arquivo, "r") as arquivo_leitura:
for linha in arquivo_leitura:
if produto_str in linha:
print(f'Ítem {produto_novo["descricao"]} já existe. ')
else:
with open(nome_arquivo, "a") as arquivo:
print(f'Adicionando ítem {produto_novo["descricao"]}. ')
arquivo.write(produto_str + '\n')
A estrutura for/else funciona da seguinte maneira. Se o loop for não for acionado em nenhuma iteração, ou, no seu caso, caso nenhum produto seja detectado, a instrução else é executada. Seria algo semelhante a se não acontecer nada durante o laço for, execute o else.
Isso deixa o código mais legível e compacto.
Fora isso, muito boa a sua iniciativa!