614 shaares
35 results
tagged
python
Basically replacing this
class A:
def __init__(self, b, c, d, e):
self.b = b
self.c = c
self.d = d
self.e = e
by
class A:
def __init__(self, b, c, d, e):
# You can edit parameters' value here before they are being stored
for k, v in vars().items():
setattr(self, k, v)
By me.
class A:
def __init__(self, b, c, d, e):
self.b = b
self.c = c
self.d = d
self.e = e
by
class A:
def __init__(self, b, c, d, e):
# You can edit parameters' value here before they are being stored
for k, v in vars().items():
setattr(self, k, v)
By me.
[path_to_script]\python-no-autoclose.py "$(FULL_CURRENT_PATH)"
In the menu Run > Run, put this in the text field and hit Save, give it a name and a key combination. Personally I used Shift+F5. Be wary than all key combinations might not work, try it to make sure or change it.
The script:
import sys
import traceback
import subprocess
import os
import pathlib
if sys.argv[1:]: # Failsafe
try:
os.chdir(str(pathlib.Path(sys.argv[1]).parent))
except Exception as e:
traceback.print_exc()
try:
subprocess.call(['python', sys.argv[1]])
except Exception as e:
traceback.print_exc()
else:
print('I\'m very confused...')
print()
input('Press Enter to exit.')
In the menu Run > Run, put this in the text field and hit Save, give it a name and a key combination. Personally I used Shift+F5. Be wary than all key combinations might not work, try it to make sure or change it.
The script:
import sys
import traceback
import subprocess
import os
import pathlib
if sys.argv[1:]: # Failsafe
try:
os.chdir(str(pathlib.Path(sys.argv[1]).parent))
except Exception as e:
traceback.print_exc()
try:
subprocess.call(['python', sys.argv[1]])
except Exception as e:
traceback.print_exc()
else:
print('I\'m very confused...')
print()
input('Press Enter to exit.')
Sauvegarder les métadonnées EXIF avec PIL.
Quick and simple backdoor to control your computers/turtles (from ComputerCraft) from outside Minecraft. Here featuring with Python.
Nice!
Bon, sachant que sebsauvage lit rarement ses mails, je vais tenter de le contacter par ici. :)
Ton implémentation est non sécurisée. C'est mal car d'autres personnes risquent de s'en inspirer sans savoir les problèmes liés à cette implémentation.
1) " Warning - When comparing the output of hexdigest() to an externally-supplied digest during a verification routine, it is recommended to use the compare_digest() function instead of the == operator to reduce the vulnerability to timing attacks." https://docs.python.org/3.4/library/hmac.html#hmac.HMAC.hexdigest
2) "The digestmod argument to the hmac.new() function may now be any hash digest name recognized by hashlib. In addition, the current behavior in which the value of digestmod defaults to MD5 is deprecated: in a future version of Python there will be no default value. (Contributed by Christian Heimes in issue 17276.)" https://docs.python.org/3/whatsnew/3.4.html#hmac
Donc il faudrait mieux commencer à spécifier une valeur pour digestmod.
Comme suggéré par l'issue (1) et cette réponse sur SO (2), je proposerais d'utiliser SHA-256 ou SHA-512 comme suit :
hmac.compare_digest(hmac.new(key, name, digestmod=hashlib.sha256).hexdigest(), signature)
(+ remplacer partout où il faut bien sure et ne pas oublier import hashlib)
(1) https://bugs.python.org/issue17276
"As of now the hash algorithm for HMAC defaults to MD5. However MD5 is considered broken. HMAC-MD5 is still ok but shall not be used in new code. Applications should slowly migrate away from HMAC-MD5 and use a more modern algorithm like HMAC-SHA256.
Therefore I propose that default digestmod should be deprecated in Python 3.4 and removed in 3.5. Starting with Python 3.5 developer are forced to choose a hash algorithm like SHA256. Our documentation shall suggest it, too."
(2) http://crypto.stackexchange.com/a/9340/18518
"Yes, there are currently no known attacks on HMAC-MD5.
[…]
However, this does not mean you should use HMAC-MD5 in new cryptosystem designs. To paraphrase Bruce Schneier, "attacks only get better, never worse." We already have practical collision attacks for MD5, showing that it does not meet its original security goals; it's possible that, any day now, someone might figure out a way to turn those into a preimage attack, which would compromise the security of HMAC-MD5. A much better choice would be to use HMAC with a hash function having no known attacks, such as SHA-2 or SHA-3."
Ton implémentation est non sécurisée. C'est mal car d'autres personnes risquent de s'en inspirer sans savoir les problèmes liés à cette implémentation.
1) " Warning - When comparing the output of hexdigest() to an externally-supplied digest during a verification routine, it is recommended to use the compare_digest() function instead of the == operator to reduce the vulnerability to timing attacks." https://docs.python.org/3.4/library/hmac.html#hmac.HMAC.hexdigest
2) "The digestmod argument to the hmac.new() function may now be any hash digest name recognized by hashlib. In addition, the current behavior in which the value of digestmod defaults to MD5 is deprecated: in a future version of Python there will be no default value. (Contributed by Christian Heimes in issue 17276.)" https://docs.python.org/3/whatsnew/3.4.html#hmac
Donc il faudrait mieux commencer à spécifier une valeur pour digestmod.
Comme suggéré par l'issue (1) et cette réponse sur SO (2), je proposerais d'utiliser SHA-256 ou SHA-512 comme suit :
hmac.compare_digest(hmac.new(key, name, digestmod=hashlib.sha256).hexdigest(), signature)
(+ remplacer partout où il faut bien sure et ne pas oublier import hashlib)
(1) https://bugs.python.org/issue17276
"As of now the hash algorithm for HMAC defaults to MD5. However MD5 is considered broken. HMAC-MD5 is still ok but shall not be used in new code. Applications should slowly migrate away from HMAC-MD5 and use a more modern algorithm like HMAC-SHA256.
Therefore I propose that default digestmod should be deprecated in Python 3.4 and removed in 3.5. Starting with Python 3.5 developer are forced to choose a hash algorithm like SHA256. Our documentation shall suggest it, too."
(2) http://crypto.stackexchange.com/a/9340/18518
"Yes, there are currently no known attacks on HMAC-MD5.
[…]
However, this does not mean you should use HMAC-MD5 in new cryptosystem designs. To paraphrase Bruce Schneier, "attacks only get better, never worse." We already have practical collision attacks for MD5, showing that it does not meet its original security goals; it's possible that, any day now, someone might figure out a way to turn those into a preimage attack, which would compromise the security of HMAC-MD5. A much better choice would be to use HMAC with a hash function having no known attacks, such as SHA-2 or SHA-3."
Oooouh, je connaissais pas inspect.getsource, c'est génial. ^-^
Petit guide d'optimisation en Python.
Nice reading.
Nice reading.
AttributeError: 'itertools.count' object has no attribute 'next'
Arf …
Le code suivant ne fonctionne donc plus en Python 3 :
>>> import itertools, collections
>>> value_to_numeric_map = collections.defaultdict(itertools.count().next)
>>> value_to_numeric_map['a']
0
>>> value_to_numeric_map['b']
1
>>> value_to_numeric_map['c']
2
>>> value_to_numeric_map['a']
0
>>> value_to_numeric_map['b']
1
La première solution venant à l'esprit serait d'avoir à instancier une variable :
>>> c = itertools.count()
>>> value_to_numeric_map = collections.defaultdict(lambda a: next(c))
Et ça fonctionne très bien.
Mais personnellement, je préfère lorsque ça reste one-line, donc voici une alternative one-line :
J'utilise lambda pour créer une encapsulation (closure).
value_to_numeric_map = collections.defaultdict((lambda c: (lambda: next(c)))(itertools.count()))
Arf …
Le code suivant ne fonctionne donc plus en Python 3 :
>>> import itertools, collections
>>> value_to_numeric_map = collections.defaultdict(itertools.count().next)
>>> value_to_numeric_map['a']
0
>>> value_to_numeric_map['b']
1
>>> value_to_numeric_map['c']
2
>>> value_to_numeric_map['a']
0
>>> value_to_numeric_map['b']
1
La première solution venant à l'esprit serait d'avoir à instancier une variable :
>>> c = itertools.count()
>>> value_to_numeric_map = collections.defaultdict(lambda a: next(c))
Et ça fonctionne très bien.
Mais personnellement, je préfère lorsque ça reste one-line, donc voici une alternative one-line :
J'utilise lambda pour créer une encapsulation (closure).
value_to_numeric_map = collections.defaultdict((lambda c: (lambda: next(c)))(itertools.count()))
Ouuuuuh, y a des trucs vachement chouettes !
Comme "1.14 Grouping adjacent list items using zip", c'est brillant, utilisé plusieurs instances du même objet iter pour regrouper les éléments ensemble. <3 (Même si j'avoue que la deuxième méthode est ptet plus lisible :D )
Ou "1.30 Using default dictionaries to represent simple trees" : Miam !
Etc.
(via http://sebsauvage.net/links/?3ASd0g )
Comme "1.14 Grouping adjacent list items using zip", c'est brillant, utilisé plusieurs instances du même objet iter pour regrouper les éléments ensemble. <3 (Même si j'avoue que la deuxième méthode est ptet plus lisible :D )
Ou "1.30 Using default dictionaries to represent simple trees" : Miam !
Etc.
(via http://sebsauvage.net/links/?3ASd0g )
Un petit Minecraft codé en 500 lignes Python.
Depuis le projet a grossit et contient + de 8000 lignes.
Depuis le projet a grossit et contient + de 8000 lignes.
Bouh, c'est mal !
" Hello,
Just noticed that the default HTML errors (like 404 Not Found) are:
1) Not using HTML5 yet.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
2) Don't indicate their encoding, which raises a message in the Fiefox console:
" The character encoding of the HTML document was not declared. The document will render with garbled text in some browser configurations if the document contains characters from outside the US-ASCII range. The character encoding of the page must be declared in the document or in the transfer protocol. "
Cordially. "
" Hello,
Just noticed that the default HTML errors (like 404 Not Found) are:
1) Not using HTML5 yet.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
2) Don't indicate their encoding, which raises a message in the Fiefox console:
" The character encoding of the HTML document was not declared. The document will render with garbled text in some browser configurations if the document contains characters from outside the US-ASCII range. The character encoding of the page must be declared in the document or in the transfer protocol. "
Cordially. "
Flask ne semble pas supporter la possibilité de retourner des générateurs comme WSGI peut le faire et je ne suis pas sûr qu'ils prévoient que ça soit le cas un jour … ( voir https://github.com/mitsuhiko/flask/pull/684 )
Mais bon perso je trouve ça super sympa de pouvoir yield du contenu lorsqu'on veut dans son code. Un peu comme je pouvais le faire avec cgi ou en PHPouet.
De plus je suis entrain de migrer d'un code pur WSGI à Flask (sous les conseils de Link Mauve si je ne me méprend pas) - pour l'instant j'en suis toujours à l'étape "c'est relou". Pourvu que ça ne dure pas -, du coup c'est plus sympa pour moi de pouvoir conserver cette façon là.
(Note: J'avais également pas envie de devoir spécifier un décorateur @generator pour toutes mes fonctions contenant un yield, j'ai donc décidé de décorer app.route directement (mais ce fut un peu plus compliqué à mettre en place))
from functools import wraps
from flask import Flask, Response, stream_with_context
app = Flask(__name__)
# Decorator to make Flask accept generators
@wraps(app.route)
def route_accept_generators(*args, **kwargs):
route = route_accept_generators.app_route(*args, **kwargs) # Getting our route decorator.
# Decorating it.
@wraps(route)
def decorated(f):
# Make so that the function that will be called return a valid Flask answer in case of returning a generator.
@wraps(f)
def function_accept_generators(*args, **kwargs):
r = f(*args, **kwargs)
if isinstance(r, types.GeneratorType):
# return Response(r, direct_passthrough=True) # Solution proposed here: http://flask.pocoo.org/mailinglist/archive/2010/11/3/using-yield/#478b0c1829b5263700da1db7d2d22c79
return Response(stream_with_context(r)) # Solution found here: http://stackoverflow.com/q/13386681/1524913
return r
return route(function_accept_generators)
return decorated
# Store the function so that it doesn't make an infinite recursion call
# Because accessing from app.route rather than directly)
# And storing it in itself instead of creating another standalone variable
route_accept_generators.app_route = app.route
app.route = route_accept_generators
Mais bon perso je trouve ça super sympa de pouvoir yield du contenu lorsqu'on veut dans son code. Un peu comme je pouvais le faire avec cgi ou en PHPouet.
De plus je suis entrain de migrer d'un code pur WSGI à Flask (sous les conseils de Link Mauve si je ne me méprend pas) - pour l'instant j'en suis toujours à l'étape "c'est relou". Pourvu que ça ne dure pas -, du coup c'est plus sympa pour moi de pouvoir conserver cette façon là.
(Note: J'avais également pas envie de devoir spécifier un décorateur @generator pour toutes mes fonctions contenant un yield, j'ai donc décidé de décorer app.route directement (mais ce fut un peu plus compliqué à mettre en place))
from functools import wraps
from flask import Flask, Response, stream_with_context
app = Flask(__name__)
# Decorator to make Flask accept generators
@wraps(app.route)
def route_accept_generators(*args, **kwargs):
route = route_accept_generators.app_route(*args, **kwargs) # Getting our route decorator.
# Decorating it.
@wraps(route)
def decorated(f):
# Make so that the function that will be called return a valid Flask answer in case of returning a generator.
@wraps(f)
def function_accept_generators(*args, **kwargs):
r = f(*args, **kwargs)
if isinstance(r, types.GeneratorType):
# return Response(r, direct_passthrough=True) # Solution proposed here: http://flask.pocoo.org/mailinglist/archive/2010/11/3/using-yield/#478b0c1829b5263700da1db7d2d22c79
return Response(stream_with_context(r)) # Solution found here: http://stackoverflow.com/q/13386681/1524913
return r
return route(function_accept_generators)
return decorated
# Store the function so that it doesn't make an infinite recursion call
# Because accessing from app.route rather than directly)
# And storing it in itself instead of creating another standalone variable
route_accept_generators.app_route = app.route
app.route = route_accept_generators
Quelques trucs avancés Python.
Savoir ça pourrait bien vous sauvez quelques heures de votre vie.
"For custom classes, implicit invocations of special methods are only guaranteed to work correctly if defined on an object’s type, not in the object’s instance dictionary." → You cannot modify magic method directly from an instance, for instance, doing that wont work:
>>> class C:
... pass
...
>>> c = C()
>>> c.__len__ = lambda: 5
>>> len(c)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'C' has no len()
"In addition to bypassing any instance attributes in the interest of correctness, implicit special method lookup generally also bypasses the __getattribute__() method even of the object’s metaclass:" → When a magic method is used and not called explicitely, then all special methods like __getattribute__ are also bypassed.
For instance:
>>> class Meta(type):
... def __getattribute__(*args):
... print("Metaclass getattribute invoked")
... return type.__getattribute__(*args)
...
>>> class C(object, metaclass=Meta):
... def __len__(self):
... return 10
... def __getattribute__(*args):
... print("Class getattribute invoked")
... return object.__getattribute__(*args)
...
>>> c = C()
>>> c.__len__() # Explicit lookup via instance
Class getattribute invoked
10
>>> type(c).__len__(c) # Explicit lookup via type
Metaclass getattribute invoked
10
>>> len(c) # Implicit lookup
10
Savoir ça pourrait bien vous sauvez quelques heures de votre vie.
"For custom classes, implicit invocations of special methods are only guaranteed to work correctly if defined on an object’s type, not in the object’s instance dictionary." → You cannot modify magic method directly from an instance, for instance, doing that wont work:
>>> class C:
... pass
...
>>> c = C()
>>> c.__len__ = lambda: 5
>>> len(c)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'C' has no len()
"In addition to bypassing any instance attributes in the interest of correctness, implicit special method lookup generally also bypasses the __getattribute__() method even of the object’s metaclass:" → When a magic method is used and not called explicitely, then all special methods like __getattribute__ are also bypassed.
For instance:
>>> class Meta(type):
... def __getattribute__(*args):
... print("Metaclass getattribute invoked")
... return type.__getattribute__(*args)
...
>>> class C(object, metaclass=Meta):
... def __len__(self):
... return 10
... def __getattribute__(*args):
... print("Class getattribute invoked")
... return object.__getattribute__(*args)
...
>>> c = C()
>>> c.__len__() # Explicit lookup via instance
Class getattribute invoked
10
>>> type(c).__len__(c) # Explicit lookup via type
Metaclass getattribute invoked
10
>>> len(c) # Implicit lookup
10
Infos intéressantes pour l'utilisation d'sqlite3 avec Python.
Je garde ça sous la main.
EDIT:
" > - Are there any peculiarities with using curs.executemany(...) vs. multiple
> curs.execute(...) ? I read a notice, sqlite3 does internally some caching,
> hence both should be similarly fast, but in my case executemany(...) is
> quite a bit faster
How many times are you calling execute vs a single executemany? The
python call overhead will add up for thousands of calls.
The relevant source code is here if you're interested:
http://svn.python.org/projects/python/trunk/Modules/_sqlite/cursor.c
> Further, I am not quite sure about the standard usage of the cursor object
> and also the proper commiting the transactions and closing the connection.
Standard usage is here:
http://docs.python.org/lib/module-sqlite3.html
If the database supports transactions then cursors automatically use
transactions. Your changes only get committed when you call .commit().
Otherwise your changes are lost.
In the specific case of sqllite, some statements (like CREATE TABLE,
ALTER TABLE, etc) also cause a commit. This is probably where your
confusion comes from. Since this isn't part of the python DB API spec
(http://www.python.org/dev/peps/pep-0249/) I wouldn't rely on it.
Otherwise you will have problems with other databases.
Also, in your specific case you're using an 'in memory' sqllite db. So
there are less concerns with losing data between db sessions, etc. But
with most databases (on disk, running across the network on a server)
this becomes important.
> Should one create a cursor of a connection and call the execute ... methods
> of the cursor -
> or is it better to call the shortcut execute etc. methods of the Connection
> object directly (as suggested in the docs:
> http://docs.python.org/lib/node351.html (or are there specific use cases for
> both approaches)?
I suggest that you use the standard cursor methods instead, so you can
run your code against non-sqllite databases. The performance etc
should be the same as using the direct method. Like the page says,
it's main benefit is consiseness.
>
> When the transactions should be commited? (creating, altering a table, or
> also selecting the results ?)
> There seem to be some implicit handling of the transactions (
> http://docs.python.org/lib/sqlite3-Controlling-Transactions.html#sqlite3-Controlling-Transactions
> ); hence I am not sure about the standard usage of these methods; the same
> is true of connection.close() - or are these calls eventually unnecessary?
As a general rule, always use .commit() and .close(). Otherwise:
- No .commit() - you will lose db changes since the last commit or
"non-DML, non-query statement" (in the case of sqllite)
- No .close() - Your database connection will only close when your db
objects are garbage collected.
> conn_tags_DB = sqlite3.connect(':memory:')
> curs = self.conn_tags_DB.cursor()
> curs.execute('CREATE TABLE IF NOT EXISTS "%s" ("%s", UNIQUE("%s"))' %
> (self.text_name, index_col_name, index_col_name))
> curs.execute(u'INSERT OR REPLACE INTO "%s"("%s") VALUES (?)' %
> (self.text_name, index_col_name), (0,))
> for new_col in act_db_columns[1:]: # adds the needed columns (except of the
> first one: index_col_name)
> curs.execute('ALTER TABLE "%s" ADD "%s" TEXT' % (self.text_name,
> new_col))
> curs.executemany('INSERT OR REPLACE INTO "%s" VALUES (%s)' %
> (self.text_name, question_marks), tags_seq)
> self.conn_tags_DB.commit()
>
> Are there maybe any comments or hints on a more elegant/efficient solution?
>
I think that dynamically creating schema (tables, based on text file
structure is a bad idea. A few reasons:
- This forces you to dynamically generate all your queries dynamically
- Not all strings are valid table/column names
- This forces the app to run as database administrator (maybe not
important for sqllite, but definitely an issue if you change to
another dbm).
- Potentially huge stability/security problems - text files can
potentially break system tables, overwrite users, etc, etc.
You're violating several rules on db design/usage.
I strongly recommend that you use a better database logic. ie, create
tables and records in advance (setup script, as db admin user if
applicable), then only use delete/insert/update/select statements (as
restricted user, if applicable).
If this is too much trouble, then I suggest storing your database in
regular Python structures instead, and use pickle/yaml/etc to write to
disk. Your current version uses a 'in memory' database, so the end
result is the same. You'll get a large performance boost also.
> Now, what's the usual way to access the database? Is it
> possible/wise/standard ... to leave the connection open for the subsequent
> queries during the whole run of the app; could even the cursor eventually be
> present as a class method, or should it rather be created repeatedly with
> each call? (After populating, the db shouldn't be modified, but only read.)
It depends. If your app is simple, single threaded, then a single
connection (global or passed through args) should be fine. Only use
multiple cursors if you need them (multiple threads, multiple
databases, multiple transaction/db isolation levels, etc).
David.
"
Je garde ça sous la main.
EDIT:
" > - Are there any peculiarities with using curs.executemany(...) vs. multiple
> curs.execute(...) ? I read a notice, sqlite3 does internally some caching,
> hence both should be similarly fast, but in my case executemany(...) is
> quite a bit faster
How many times are you calling execute vs a single executemany? The
python call overhead will add up for thousands of calls.
The relevant source code is here if you're interested:
http://svn.python.org/projects/python/trunk/Modules/_sqlite/cursor.c
> Further, I am not quite sure about the standard usage of the cursor object
> and also the proper commiting the transactions and closing the connection.
Standard usage is here:
http://docs.python.org/lib/module-sqlite3.html
If the database supports transactions then cursors automatically use
transactions. Your changes only get committed when you call .commit().
Otherwise your changes are lost.
In the specific case of sqllite, some statements (like CREATE TABLE,
ALTER TABLE, etc) also cause a commit. This is probably where your
confusion comes from. Since this isn't part of the python DB API spec
(http://www.python.org/dev/peps/pep-0249/) I wouldn't rely on it.
Otherwise you will have problems with other databases.
Also, in your specific case you're using an 'in memory' sqllite db. So
there are less concerns with losing data between db sessions, etc. But
with most databases (on disk, running across the network on a server)
this becomes important.
> Should one create a cursor of a connection and call the execute ... methods
> of the cursor -
> or is it better to call the shortcut execute etc. methods of the Connection
> object directly (as suggested in the docs:
> http://docs.python.org/lib/node351.html (or are there specific use cases for
> both approaches)?
I suggest that you use the standard cursor methods instead, so you can
run your code against non-sqllite databases. The performance etc
should be the same as using the direct method. Like the page says,
it's main benefit is consiseness.
>
> When the transactions should be commited? (creating, altering a table, or
> also selecting the results ?)
> There seem to be some implicit handling of the transactions (
> http://docs.python.org/lib/sqlite3-Controlling-Transactions.html#sqlite3-Controlling-Transactions
> ); hence I am not sure about the standard usage of these methods; the same
> is true of connection.close() - or are these calls eventually unnecessary?
As a general rule, always use .commit() and .close(). Otherwise:
- No .commit() - you will lose db changes since the last commit or
"non-DML, non-query statement" (in the case of sqllite)
- No .close() - Your database connection will only close when your db
objects are garbage collected.
> conn_tags_DB = sqlite3.connect(':memory:')
> curs = self.conn_tags_DB.cursor()
> curs.execute('CREATE TABLE IF NOT EXISTS "%s" ("%s", UNIQUE("%s"))' %
> (self.text_name, index_col_name, index_col_name))
> curs.execute(u'INSERT OR REPLACE INTO "%s"("%s") VALUES (?)' %
> (self.text_name, index_col_name), (0,))
> for new_col in act_db_columns[1:]: # adds the needed columns (except of the
> first one: index_col_name)
> curs.execute('ALTER TABLE "%s" ADD "%s" TEXT' % (self.text_name,
> new_col))
> curs.executemany('INSERT OR REPLACE INTO "%s" VALUES (%s)' %
> (self.text_name, question_marks), tags_seq)
> self.conn_tags_DB.commit()
>
> Are there maybe any comments or hints on a more elegant/efficient solution?
>
I think that dynamically creating schema (tables, based on text file
structure is a bad idea. A few reasons:
- This forces you to dynamically generate all your queries dynamically
- Not all strings are valid table/column names
- This forces the app to run as database administrator (maybe not
important for sqllite, but definitely an issue if you change to
another dbm).
- Potentially huge stability/security problems - text files can
potentially break system tables, overwrite users, etc, etc.
You're violating several rules on db design/usage.
I strongly recommend that you use a better database logic. ie, create
tables and records in advance (setup script, as db admin user if
applicable), then only use delete/insert/update/select statements (as
restricted user, if applicable).
If this is too much trouble, then I suggest storing your database in
regular Python structures instead, and use pickle/yaml/etc to write to
disk. Your current version uses a 'in memory' database, so the end
result is the same. You'll get a large performance boost also.
> Now, what's the usual way to access the database? Is it
> possible/wise/standard ... to leave the connection open for the subsequent
> queries during the whole run of the app; could even the cursor eventually be
> present as a class method, or should it rather be created repeatedly with
> each call? (After populating, the db shouldn't be modified, but only read.)
It depends. If your app is simple, single threaded, then a single
connection (global or passed through args) should be fine. Only use
multiple cursors if you need them (multiple threads, multiple
databases, multiple transaction/db isolation levels, etc).
David.
"
Je sens que je vais oublier ça …
"Python looks up special methods only on the class, ignoring anything defined on the instance."
"Python looks up special methods only on the class, ignoring anything defined on the instance."
Interesdasting
Ça y est, je me sers de mon shaarli pour envoyer des messages aux personnes offlines maintenant …
Désolé buddy j'avais pas vu ton message j'étais en mode veille.
Du coup, si tu (ou d'autres) sont intéressés par un projet Python, n'hésite pas à check :
https://github.com/JeromeJ/Devutopia
http://devutopia.net/
Je préviens que le design est pas encore fait :p
(Et pour la licence on va sûrement passer en CopyLeft)
(Wink, wink, les tags ;) à ta demande expresse :D)
Désolé buddy j'avais pas vu ton message j'étais en mode veille.
Du coup, si tu (ou d'autres) sont intéressés par un projet Python, n'hésite pas à check :
https://github.com/JeromeJ/Devutopia
http://devutopia.net/
Je préviens que le design est pas encore fait :p
(Et pour la licence on va sûrement passer en CopyLeft)
(Wink, wink, les tags ;) à ta demande expresse :D)
Commen j'ai pas moyen de te mailer ou autres, je poste ça ici et ptet qu'ainsi tu verras mon message.
J'ai plus simple que ce que la solution que je t'avais proposé.
À savoir, ça : [k for k in myDict if k in myOtherDict] mais avec des .keys() en plus inutile.
En fait c'était tout con, on peut faire ça :
>>> {"a":22, "b":33, "c":24}.keys() & {"a":33, "b":57, "d":78}
{'a', 'b'}
.keys() renvoit une view qui se comporte comme un set, d'où la possibilité d'utiliser l'opérateur "&" normalement propre aux sets. ( http://www.python.org/dev/peps/pep-3106/ )
Et pas vraiment besoin d'utiliser .keys sur le dico de droite (je pense pas que ça impacte les performances), le "set-like" returner par .keys() sait effectuer l'opération "&" sur un dict (car par défaut quand tu itères un dict, ça itère sur les clés, faut utiliser .items() ou .values() sinon).
(Wink, wink, les tags ;) )
J'ai plus simple que ce que la solution que je t'avais proposé.
À savoir, ça : [k for k in myDict if k in myOtherDict] mais avec des .keys() en plus inutile.
En fait c'était tout con, on peut faire ça :
>>> {"a":22, "b":33, "c":24}.keys() & {"a":33, "b":57, "d":78}
{'a', 'b'}
.keys() renvoit une view qui se comporte comme un set, d'où la possibilité d'utiliser l'opérateur "&" normalement propre aux sets. ( http://www.python.org/dev/peps/pep-3106/ )
Et pas vraiment besoin d'utiliser .keys sur le dico de droite (je pense pas que ça impacte les performances), le "set-like" returner par .keys() sait effectuer l'opération "&" sur un dict (car par défaut quand tu itères un dict, ça itère sur les clés, faut utiliser .items() ou .values() sinon).
(Wink, wink, les tags ;) )
Mon cher ami,
Le Web le sera. Il se doit de l'être, de franchir le cap.
Tu n'as hélas sûrement pas vu ces _success stories_ similaires mais pas aussi ambitieuses. Il y a beaucoup d'espoir.
Ça pourrait changer le monde.
Le Web passera par là, avec ou sans moi, il n'a plus le choix.
Alors, tâchons juste d'aider son accomplissement comme il se doit, faisons en sorte que ça soit beau, et ooh ça le sera.
Merci pour les liens. (J'viens de finir de re-re-regarder Cyrano de Bergerac - cela explique peut-être ma plume)
Le Web le sera. Il se doit de l'être, de franchir le cap.
Tu n'as hélas sûrement pas vu ces _success stories_ similaires mais pas aussi ambitieuses. Il y a beaucoup d'espoir.
Ça pourrait changer le monde.
Le Web passera par là, avec ou sans moi, il n'a plus le choix.
Alors, tâchons juste d'aider son accomplissement comme il se doit, faisons en sorte que ça soit beau, et ooh ça le sera.
Merci pour les liens. (J'viens de finir de re-re-regarder Cyrano de Bergerac - cela explique peut-être ma plume)