2008-08-08 9 views
13

Fondamentalement, j'ai écrit une API sur www.thetvdb.com en Python. Le code actuel peut être trouvé here.Meilleure façon de résumer les données de saison/émission/épisode

Il saisit les données de l'API comme l'a demandé, et doit stocker les données en quelque sorte, et le rendre disponible en faisant:

print tvdbinstance[1][23]['episodename'] # get the name of episode 23 of season 1 

Quelle est la « meilleure » façon de faire abstraction de ces données au sein de la classe Tvdb() ?

I utilisé à l'origine d'une Dict() prolongée qui a créé automatiquement des sous-dicts (pour que vous puissiez faire x[1][2][3][4] = "something" sans avoir à faire if x[1].has_key(2): x[1][2] = [] et ainsi de suite)

Ensuite, je viens stockées les données en faisant self.data[show_id][season_number][episode_number][attribute_name] = "something"

Cela a fonctionné ok, mais il n'y avait pas de moyen facile de vérifier si x[3][24] était censé exister ou non (donc je ne pouvais pas lever l'exception season_not_found).

il est actuellement en utilisant quatre classes: ShowContainer, Show, Season et Episode. Chacun est un dict très basique, auquel je peux facilement ajouter des fonctionnalités supplémentaires (la fonction search() sur Show() par exemple). Chacun a un __setitem__, __getitem_ et has_key.

Cela fonctionne très bien, je peux vérifier dans les spectacles si elle a cette saison dans self.data dict, sinon, raise season_not_found. Je peux également vérifier Season() s'il a cet épisode et ainsi de suite.

Le problème est maintenant que cela se présente comme dict, mais ne pas toutes les fonctionnalités, et parce que je suis remplaçant les fonctions __getitem__ et __setitem__, il est facile d'appeler accidentellement récursive __getitem__ (donc je ne suis pas sûr si l'extension de la classe Dict provoque des problèmes).

L'autre petit problème est l'ajout de données dans la dict, c'est beaucoup plus de travail que l'ancienne méthode Dict (qui était self.data[seas_no][ep_no]['attribute'] = 'something'). Voir _setItem et _setData. Ce n'est pas trop mal, car il s'agit actuellement d'une interface API en lecture seule (les utilisateurs de l'API ne devraient donc jamais récupérer de données, pas ajouter plus), mais c'est à peine ... Elégant.

Je pense que le système des séries de classes est probablement le meilleur moyen, mais est-ce que quelqu'un a une meilleure idée pour stocker les données? Et serait étendre les ShowContainer/etc classes avec Dict causer des problèmes?

Répondre

5

OK, ce dont vous avez besoin est classobj du nouveau module. Cela vous permettrait de construire dynamiquement des classes d'exception (classobj prend une chaîne comme argument pour le nom de la classe).

import new 
myexc=new.classobj("ExcName",(Exception,),{}) 
i=myexc("This is the exc msg!") 
raise i 

cela vous donne:

Traceback (most recent call last): 
File "<stdin>", line 1, in <module> 
__main__.ExcName: This is the exc msg! 

rappelez-vous que vous pouvez toujours obtenir le nom de la classe par:

self.__class__.__name__ 

Ainsi, après une chaîne mutiler et concaténation, vous devriez être en mesure de obtenir le nom de classe d'exception approprié et construire un objet de classe en utilisant ce nom, puis lever cette exception.

P.S.- Vous pouvez également augmenter les chaînes, mais cela est obsolète.

raise(self.__class__.__name__+"Exception") 
3

Pourquoi ne pas utiliser SQLite? Il y a un bon support en Python et vous pouvez écrire des requêtes SQL pour extraire les données. Voici les docs Python pour sqlite3


Si vous ne souhaitez pas utiliser SQLite que vous pourriez faire un tableau de dicts.

episodes = [] 
episodes.append({'season':1, 'episode': 2, 'name':'Something'}) 
episodes.append({'season':1, 'episode': 2, 'name':'Something', 'actors':['Billy Bob', 'Sean Penn']}) 

De cette façon, vous ajoutez des métadonnées à un enregistrement et une recherche très facilement

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']) 
0

Je l'ai fait quelque chose de similaire dans le passé et utilisé un document XML en mémoire comme une base de données hiérarchique rapide et sale pour le stockage. Vous pouvez stocker chaque spectacle/saison/épisode en tant qu'élément (imbriqué de manière appropriée) et les attributs de ces éléments en tant qu'attributs xml sur les éléments. Ensuite, vous pouvez utiliser XQuery pour récupérer des informations. Je ne suis pas un mec Python, donc je ne sais pas à quoi ressemble votre support xml.

NOTE 2: Vous aurez besoin de profiler cela parce que ce sera plus grand et plus lent que la solution que vous avez déjà. Assez probable si vous faites un traitement à haut volume, XML ne sera probablement pas votre ami.

0

Je ne comprends pas cette partie ici:

Cela a bien fonctionné, mais il n'y avait pas de moyen facile de vérifier si x [3] [24] était censé exister ou non (donc je ne pourrais pas » t soulever l'exception season_not_found)

il y a une façon de le faire - appelé à :

>>>x={} 
>>>x[1]={} 
>>>x[1][2]={} 
>>>x 
{1: {2: {}}} 
>>> 2 in x[1] 
True 
>>> 3 in x[1] 
False 

ce qui semble être le problème avec ça?

0

Bartosz/Pour clarifier « Cela a bien fonctionné, mais il n'y avait pas de moyen facile de vérifier si x [3] [24] était censé exister ou non »

x['some show'][3][24] retourneraient saison 3, épisode 24 " certains montrent ". S'il n'y avait pas de saison 3, je veux que le pseudo-dict pour élever tvdb_seasonnotfound, si « certains spectacle » n'existe pas, puis relevez tvdb_shownotfound

Le système actuel d'une série de classes, chacune avec un __getitem__ - vérifie Afficher if self.seasons.has_key(requested_season_number), la classe de saison vérifie if self.episodes.has_key(requested_episode_number) et ainsi de suite.

Il fonctionne, mais il y semble être beaucoup de code répété (chaque classe est fondamentalement la même, mais soulève une autre erreur)