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)
Personnes intéressées pour rendre les avantages des systèmes décentralisés en informatique accessibles à tout le monde ? :D
Anyone interested to give to everyone the advantages of decentralized systems (especially in the programming world, for instance like git, …)?
Contact-me ^-^
Anyone interested to give to everyone the advantages of decentralized systems (especially in the programming world, for instance like git, …)?
Contact-me ^-^
Plein de chouettes conseils ☺
Notamment, le debug mode pour les REGEX que j'ignorais. Really neat. (J'espère ne pas l'oublier celui là :p)
Dommage que la question soit fermées, certaines réponses auraient, je trouve, méritées des commentaires ou éditions.
EDIT: Woah, y a carrément 7 pages Oo
Je n'avais jamais vu ça, c'est excellent : http://stackoverflow.com/a/4602518/1524913
>>> first,second,*rest = (1,2,3,4,5,6,7,8)
>>> first
1
>>> second
2
>>> rest
[3, 4, 5, 6, 7, 8]
Et
>>> first,*rest,last = (1,2,3,4,5,6,7,8)
>>> first
1
>>> rest
[2, 3, 4, 5, 6, 7]
>>> last
8
Notamment, le debug mode pour les REGEX que j'ignorais. Really neat. (J'espère ne pas l'oublier celui là :p)
Dommage que la question soit fermées, certaines réponses auraient, je trouve, méritées des commentaires ou éditions.
EDIT: Woah, y a carrément 7 pages Oo
Je n'avais jamais vu ça, c'est excellent : http://stackoverflow.com/a/4602518/1524913
>>> first,second,*rest = (1,2,3,4,5,6,7,8)
>>> first
1
>>> second
2
>>> rest
[3, 4, 5, 6, 7, 8]
Et
>>> first,*rest,last = (1,2,3,4,5,6,7,8)
>>> first
1
>>> rest
[2, 3, 4, 5, 6, 7]
>>> last
8
Ahaha x'D Courage ^^
Je me suis tappé la tête contre le mur pendant plusieurs jours avec l'encodage en PHP et même un peu en Python (surtout le 2 qui me casse les noises :o)
Mon site se convertit en UTF-8, yeay !! :DD
Au fait, j'crois que tu n'utilises pas de BDD genre MySQL toi, mais sachez que, en plus de tous les autres trucs qui font chier en PHP vis-à-vis de l'UTF-8 mal géré nativement, MySQL utilise également un encodage à la con de base pour ces communications :/ donc rien à voir avec la façon dont vous stockez vos chaines dans la BDD. Quand vous les récup, il convertit en ISO quelque chose ce con :o (lol) sauf si vous faites la requête SET NAMES utf-8.
Rappel: Utilisez toujours et partout UTF-8. Les problèmes viennent des autres encodages !! Si vous ne prenez pas la bonne habitude de mettre de l'utf-8 partout, vous "risquez" d'en chier lorsque vous voudrez reconvertir en UTF-8 (car c'est un milliard de fois mieux).
Je me suis tappé la tête contre le mur pendant plusieurs jours avec l'encodage en PHP et même un peu en Python (surtout le 2 qui me casse les noises :o)
Mon site se convertit en UTF-8, yeay !! :DD
Au fait, j'crois que tu n'utilises pas de BDD genre MySQL toi, mais sachez que, en plus de tous les autres trucs qui font chier en PHP vis-à-vis de l'UTF-8 mal géré nativement, MySQL utilise également un encodage à la con de base pour ces communications :/ donc rien à voir avec la façon dont vous stockez vos chaines dans la BDD. Quand vous les récup, il convertit en ISO quelque chose ce con :o (lol) sauf si vous faites la requête SET NAMES utf-8.
Rappel: Utilisez toujours et partout UTF-8. Les problèmes viennent des autres encodages !! Si vous ne prenez pas la bonne habitude de mettre de l'utf-8 partout, vous "risquez" d'en chier lorsque vous voudrez reconvertir en UTF-8 (car c'est un milliard de fois mieux).
Voilà ma version, j'en suis plutôt satisfait :
As PHP doesn't really have a proper alternative to str.format in Python, I decided to implement my very simple own which as most of the basic functionnalitites of the Python's one.
function format($msg, $vars)
{
$vars = (array)$vars;
$msg = preg_replace_callback('#\{\}#', function($r){
static $i = 0;
return '{'.($i++).'}';
}, $msg);
return str_replace(
array_map(function($k) {
return '{'.$k.'}';
}, array_keys($vars)),
array_values($vars),
$msg
);
}
# Samples:
# Hello foo and bar
echo format('Hello {} and {}.', array('foo', 'bar'));
# Hello Mom
echo format('Hello {}', 'Mom');
# Hello foo, bar and foo
echo format('Hello {}, {1} and {0}', array('foo', 'bar'));
# I'm not a fool nor a bar
echo format('I\'m not a {foo} nor a {}', array('foo' => 'fool', 'bar'));
1. The order doesn't matter,
2. You can omit the name/number if you want it to simply increment (the first {} matched will be transformed into {0}, etc),
3. You can name your parameters,
4. You can mix the three other points.
As PHP doesn't really have a proper alternative to str.format in Python, I decided to implement my very simple own which as most of the basic functionnalitites of the Python's one.
function format($msg, $vars)
{
$vars = (array)$vars;
$msg = preg_replace_callback('#\{\}#', function($r){
static $i = 0;
return '{'.($i++).'}';
}, $msg);
return str_replace(
array_map(function($k) {
return '{'.$k.'}';
}, array_keys($vars)),
array_values($vars),
$msg
);
}
# Samples:
# Hello foo and bar
echo format('Hello {} and {}.', array('foo', 'bar'));
# Hello Mom
echo format('Hello {}', 'Mom');
# Hello foo, bar and foo
echo format('Hello {}, {1} and {0}', array('foo', 'bar'));
# I'm not a fool nor a bar
echo format('I\'m not a {foo} nor a {}', array('foo' => 'fool', 'bar'));
1. The order doesn't matter,
2. You can omit the name/number if you want it to simply increment (the first {} matched will be transformed into {0}, etc),
3. You can name your parameters,
4. You can mix the three other points.
Ouh, j'ai hâte perso, elle a l'air vraiment chouette à utiliser cette classe.
(via http://stackoverflow.com/a/1695250/1524913 )
(via http://stackoverflow.com/a/1695250/1524913 )
Cool ça :o
Ce que j'avais beaucoup aimé aussi c'est la possibilité de faire du Java depuis Python (en faite il s'agissait de coder en Python puis compiler en bytecode Java. J'aimerais bien faire un mod pour Minecraft ainsi :p)
Ce que j'avais beaucoup aimé aussi c'est la possibilité de faire du Java depuis Python (en faite il s'agissait de coder en Python puis compiler en bytecode Java. J'aimerais bien faire un mod pour Minecraft ainsi :p)
There might be some easier ways to do that but that's the easiest I found so far…
As usual, not surprisingly, Python is better (IMO).
Python:
try:
foo()
except ValueError:
bar()
PHP:
It's actually pretty easy when you implement your own errors (throw new Exception then catch it with a try…catch) but how to catch errors this easily and being able to handle them that easily? Well, turn them into exceptions!
set_error_handler(function($errno, $errstr){throw new Exception($errno);});
try
{
file_get_contents('lol');
}
catch(Exception $e)
{
echo 'Error n°',$e->getMessage();
}
restore_error_handler();
I still prefer Python… I think I'll always do. </PHPTROLL> </PYTHONFAN>
As usual, not surprisingly, Python is better (IMO).
Python:
try:
foo()
except ValueError:
bar()
PHP:
It's actually pretty easy when you implement your own errors (throw new Exception then catch it with a try…catch) but how to catch errors this easily and being able to handle them that easily? Well, turn them into exceptions!
set_error_handler(function($errno, $errstr){throw new Exception($errno);});
try
{
file_get_contents('lol');
}
catch(Exception $e)
{
echo 'Error n°',$e->getMessage();
}
restore_error_handler();
I still prefer Python… I think I'll always do. </PHPTROLL> </PYTHONFAN>
Tiens, je connaissais pas, c'est marrant cette notation :)
print('\N{left-pointing double angle quotation mark}') # Output: «
Et pour avoir le nom d'un caractère :
import unicodedata
print(unicodedata.name('«')) # Output: LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
print('\N{left-pointing double angle quotation mark}') # Output: «
Et pour avoir le nom d'un caractère :
import unicodedata
print(unicodedata.name('«')) # Output: LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
Why?! Seriously guys…
So this is an piece of my code :
messages = {'chooseYourLang': {'fr': 'Saisis {} pour le français.', 'en': 'Type {} for the English.'}}
langs = ('fr', 'en')
# This…
for n, (code, msg) in enumerate(messages['chooseYourLang'].items(), 1):
print('{}. [{}] {}'.format(n, code.upper(), msg.format(n)))
# Always become that!!
print('\n'.join('{}. [{}] {}'.format(n, lang.upper(), messages['chooseYourLang'][lang].format(n)) for n, lang in enumerate(langs, 1)))
# I just wanted to have it always in this order (fr then en) without needing to use collections.OrderedDict
Fine for me though (more or less)…
So I guess my answer to my own question could be "Just cause I can!" but I don't know… It -always- just happens suddenly, without a warning. Weird.
Do you understand me? Do you share this with me? Am I alone on this planet? Why are we? Who am I? Maybe I should take a break :D
So this is an piece of my code :
messages = {'chooseYourLang': {'fr': 'Saisis {} pour le français.', 'en': 'Type {} for the English.'}}
langs = ('fr', 'en')
# This…
for n, (code, msg) in enumerate(messages['chooseYourLang'].items(), 1):
print('{}. [{}] {}'.format(n, code.upper(), msg.format(n)))
# Always become that!!
print('\n'.join('{}. [{}] {}'.format(n, lang.upper(), messages['chooseYourLang'][lang].format(n)) for n, lang in enumerate(langs, 1)))
# I just wanted to have it always in this order (fr then en) without needing to use collections.OrderedDict
Fine for me though (more or less)…
So I guess my answer to my own question could be "Just cause I can!" but I don't know… It -always- just happens suddenly, without a warning. Weird.
Do you understand me? Do you share this with me? Am I alone on this planet? Why are we? Who am I? Maybe I should take a break :D
Bon, sûrement peu d'entres vous en auront besoin un jour mais sait-on jamais :) je partage !
Personnellement, ça m'arrive encore assez bien souvent de m'endormir sur une musique de relaxation pour m'aider mais une fois n'est pas coutume, la musique que je voulais écouter était un flux continu (radio en ligne) donc VLC ne se serait jamais arrêté et mon PC ne ce serait jamais mis en veille, il aurait continué à chanter toute la nuit en utilisant ma bande passante pour rien qui plus est :p
La version actuelle est pour Windows seulement mais je sais de fait que faire la version Linux (ou carrément directement multiplateforme) serait un jeu d'enfant.
Personnellement, ça m'arrive encore assez bien souvent de m'endormir sur une musique de relaxation pour m'aider mais une fois n'est pas coutume, la musique que je voulais écouter était un flux continu (radio en ligne) donc VLC ne se serait jamais arrêté et mon PC ne ce serait jamais mis en veille, il aurait continué à chanter toute la nuit en utilisant ma bande passante pour rien qui plus est :p
La version actuelle est pour Windows seulement mais je sais de fait que faire la version Linux (ou carrément directement multiplateforme) serait un jeu d'enfant.
-.- En Python, c'est super simple :/
En PHP faudrait que chaque fonction soit référencée dans un array du style array('functionName' => 'functionName'); mais j'ignore quel serait l'impact sur les performances :/
Et quand bien même, ça a encore des limitations.
En Python:
L'application:
def a():
pass
# And you can call it normally
Le patch:
def a():
# Do some more stuff
a() # Then call "a" normally
(C'est le principe d'un décorateur quoi, mais je pourrais aussi simplement remplacer la fonction sans appeler l'ancienne fonction)
En PHP:
function lol()
{
}
$functions = array('lol' => 'lol');
# And you call it using $functions['lol']();
Le patch:
$functions['lol'] = function() use($functions)
{
static $lol;
if($lol === null) $lol = $functions['lol'];
# Do some more stuff …
$lol();
};
# To call it, it's the same than before $functions['lol']();
EDIT: Il existe bien des techniques pour créer des "Décorateurs" en PHP (aka surcharger une fonction) (à base de POO) mais ... meh. J'accroche pas perso, j'trouve ça lourd.
En PHP faudrait que chaque fonction soit référencée dans un array du style array('functionName' => 'functionName'); mais j'ignore quel serait l'impact sur les performances :/
Et quand bien même, ça a encore des limitations.
En Python:
L'application:
def a():
pass
# And you can call it normally
Le patch:
def a():
# Do some more stuff
a() # Then call "a" normally
(C'est le principe d'un décorateur quoi, mais je pourrais aussi simplement remplacer la fonction sans appeler l'ancienne fonction)
En PHP:
function lol()
{
}
$functions = array('lol' => 'lol');
# And you call it using $functions['lol']();
Le patch:
$functions['lol'] = function() use($functions)
{
static $lol;
if($lol === null) $lol = $functions['lol'];
# Do some more stuff …
$lol();
};
# To call it, it's the same than before $functions['lol']();
EDIT: Il existe bien des techniques pour créer des "Décorateurs" en PHP (aka surcharger une fonction) (à base de POO) mais ... meh. J'accroche pas perso, j'trouve ça lourd.
Une liste de quelques exercices (à difficulté croissante) pour s'entrainer à Python (+ liste de liens externes connu ou non, tels que le projet Euler)
Site qui propose de dire quelle fonction utiliser en Python à partir d'une fonction PHP.
Le concept est juste sensationnel :)
Le concept est juste sensationnel :)
Magnifique wiki très complet et pratique.
Néophyte en programmation ou pas, langage de haut niveau ou pas, tout n'est pas toujours intuitif et on apprend parfois tous les jours :) Alors je partage !
(Rappel: haut niveau = proche de l'être humain, ex: Python
bas niveau = proche de la machine, ex: C++)
Lien direct vers la version anglaise: http://sebsauvage.net/python/snyppets/#binary_repr
J'en parle aussi dans mon article sur les ptits trucs python: https://www.olissea.com/doc/?artId=6 . J'ai même rajouter une méthode pour contourner le problème car la seconde proposée par sebsauvage ne fonctionne pas toujours en Python 3 :o
(Rappel: haut niveau = proche de l'être humain, ex: Python
bas niveau = proche de la machine, ex: C++)
Lien direct vers la version anglaise: http://sebsauvage.net/python/snyppets/#binary_repr
J'en parle aussi dans mon article sur les ptits trucs python: https://www.olissea.com/doc/?artId=6 . J'ai même rajouter une méthode pour contourner le problème car la seconde proposée par sebsauvage ne fonctionne pas toujours en Python 3 :o