Melhor maneira de abstrair dados de temporada/programa/episódio
-
08-06-2019 - |
Pergunta
Basicamente, escrevi uma API para www.thetvdb.com em Python.O código atual pode ser encontrado aqui.
Ele captura dados da API conforme solicitado e precisa armazená-los de alguma forma e disponibilizá-los fazendo:
print tvdbinstance[1][23]['episodename'] # get the name of episode 23 of season 1
Qual é a "melhor" maneira de abstrair esses dados dentro do Tvdb()
aula?
Eu originalmente usei um estendido Dict()
que criou sub-dictos automaticamente (para que você pudesse fazer x[1][2][3][4] = "something"
sem ter que fazer if x[1].has_key(2): x[1][2] = []
e assim por diante)
Então eu apenas armazenei os dados fazendo self.data[show_id][season_number][episode_number][attribute_name] = "something"
Isso funcionou bem, mas não havia uma maneira fácil de verificar se x[3][24]
deveria existir ou não (então não pude gerar a exceção season_not_found).
Atualmente está usando quatro classes: ShowContainer
, Show
, Season
e Episode
.Cada um é um ditado muito básico, ao qual posso facilmente adicionar funcionalidades extras (o search()
função ativada Show()
por exemplo).Cada um tem um __setitem__
, __getitem_
e has_key
.
Isso funciona muito bem, posso verificar nos programas se tem aquela temporada self.data
dite, se não, raise season_not_found
.Também posso fazer check-in Season()
se tiver aquele episódio e assim por diante.
O problema agora é que ele se apresenta como um dict, mas não possui todas as funcionalidades, e como estou substituindo o __getitem__
e __setitem__
funções, é fácil acidentalmente chamar recursivamente __getitem__
(então não tenho certeza se estender o Dict
classe causará problemas).
O outro pequeno problema é que adicionar dados ao dict dá muito mais trabalho do que o antigo Dict
método (que foi self.data[seas_no][ep_no]['attribute'] = 'something'
).Ver _setItem
e _setData
.Não é tão ruim, já que atualmente é apenas uma interface de API somente leitura (portanto, os usuários da API devem apenas recuperar dados, e não adicionar mais), mas dificilmente é...Elegante.
Acho que o sistema de séries de classes é provavelmente o melhor caminho, mas alguém tem uma ideia melhor para armazenar os dados?E estenderia o ShowContainer
/etc aulas com Dict
Causar problemas?
Solução
OK, o que você precisa é classobj
do novo módulo.Isso permitiria construir classes de exceção dinamicamente (classobj
recebe uma string como argumento para o nome da classe).
import new
myexc=new.classobj("ExcName",(Exception,),{})
i=myexc("This is the exc msg!")
raise i
isso lhe dá:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
__main__.ExcName: This is the exc msg!
lembre-se que você sempre pode obter o nome da classe através de:
self.__class__.__name__
Portanto, após alguma manipulação e concatenação de strings, você poderá obter o nome da classe de exceção apropriado e construir um objeto de classe usando esse nome e, em seguida, gerar essa exceção.
P.S.- você também pode aumentar strings, mas isso está obsoleto.
raise(self.__class__.__name__+"Exception")
Outras dicas
Por que não usar SQLite?Há um bom suporte em Python e você pode escrever consultas SQL para extrair os dados.Aqui estão os documentos do Python para sqlite3
Se você não quiser usar o SQLite, poderá fazer uma série de dictos.
episodes = []
episodes.append({'season':1, 'episode': 2, 'name':'Something'})
episodes.append({'season':1, 'episode': 2, 'name':'Something', 'actors':['Billy Bob', 'Sean Penn']})
Dessa forma você adiciona metadados a qualquer registro e pesquisa com muita facilidade
season_1 = [e for e in episodes if e['season'] == 1]
billy_bob = [e for e in episodes if 'actors' in e and 'Billy Bob' in e['actors']]
for episode in billy_bob:
print "Billy bob was in Season %s Episode %s" % (episode['season'], episode['episode'])
Já fiz algo semelhante no passado e usei um documento XML na memória como um banco de dados hierárquico rápido e sujo para armazenamento.Você pode armazenar cada programa/temporada/episódio como um elemento (aninhado apropriadamente) e atributos dessas coisas como atributos xml nos elementos.Então você pode usar o XQuery para recuperar informações.
OBSERVAÇÃO: Não sou um cara de Python, então não sei como é o seu suporte a xml.
NOTA 2: Você desejará traçar esse perfil porque será maior e mais lento do que a solução que você já possui.Provavelmente, se você estiver realizando algum processamento de alto volume, o XML provavelmente não será seu amigo.
Não entendi essa parte aqui:
Isso funcionou bem, mas não havia uma maneira fácil de verificar se x[3][24] deveria existir ou não (então não pude gerar a exceção season_not_found)
Existe uma maneira de fazer isso - chamada em:
>>>x={}
>>>x[1]={}
>>>x[1][2]={}
>>>x
{1: {2: {}}}
>>> 2 in x[1]
True
>>> 3 in x[1]
False
qual parece ser o problema com isso?
Bartosz/Para esclarecer "Isso funcionou bem, mas não havia uma maneira fácil de verificar se x[3][24] deveria existir ou não"
x['some show'][3][24]
retornaria a 3ª temporada, episódio 24 de "some show".Se não houve 3ª temporada, quero que o pseudo-dict aumente tvdb_seasonnotfound, se "algum programa" não existir, então aumente tvdb_shownotfound
O sistema atual de uma série de aulas, cada uma com um __getitem__
- Mostrar cheques if self.seasons.has_key(requested_season_number)
, a classe Temporada verifica if self.episodes.has_key(requested_episode_number)
e assim por diante.
Funciona, mas parece haver muito código repetido (cada classe é basicamente a mesma, mas gera um erro diferente)