Path: csiph.com!usenet.pasdenom.info!news.redatomik.org!newsfeed.xs4all.nl!newsfeed3.news.xs4all.nl!xs4all!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.003 X-Spam-Evidence: '*H*': 0.99; '*S*': 0.00; 'python,': 0.02; 'attributes': 0.07; 'extent': 0.07; 'objects,': 0.07; 'table.': 0.07; '"but': 0.09; 'committing': 0.09; 'iterate': 0.09; 'res': 0.09; 'rows': 0.09; 'tuple': 0.09; 'example:': 0.11; '1,000': 0.16; '24,': 0.16; 'from:addr:rosuav': 0.16; 'from:name:chris angelico': 0.16; 'iterating': 0.16; 'sqlalchemy': 0.16; 'wrote:': 0.16; '>>>': 0.20; 'student': 0.20; 'pages,': 0.20; 'to:name :python-list@python.org': 0.20; 'enforce': 0.22; 'latter': 0.22; 'code.': 0.23; '2015': 0.23; "i've": 0.24; 'header:In-Reply-To:1': 0.24; 'sort': 0.25; 'question': 0.26; 'chris': 0.26; 'equivalent': 0.27; 'message-id:@mail.gmail.com': 0.28; 'asked': 0.28; '(it': 0.29; 'objects': 0.29; 'that.': 0.30; 'too.': 0.30; "we're": 0.30; 'programmers': 0.31; 'query': 0.31; 'code': 0.31; 'table': 0.32; 'received:google.com': 0.34; 'advice': 0.35; 'there,': 0.35; 'drop': 0.35; 'to:addr:python-list': 0.35; 'clear': 0.35; 'something': 0.35; 'list': 0.35; 'but': 0.36; 'possible': 0.36; 'quite': 0.37; 'two': 0.37; 'subject:: ': 0.37; 'rather': 0.38; 'doing': 0.38; 'someone': 0.38; 'pm,': 0.39; 'enough': 0.39; 'performance': 0.39; 'to:addr:python.org': 0.39; 'seem': 0.39; 'some': 0.40; 'your': 0.60; 'entire': 0.61; 'here.': 0.61; 'more': 0.62; 'above,': 0.63; 'skip:n 10': 0.63; '>>>>>': 0.66; 'acts': 0.72; 'chrisa': 0.84; 'dumb': 0.84; 'quicker': 0.84; 'subject:good': 0.84; 'subject:tool': 0.84; 'transactions': 0.91; 'hundred': 0.96 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :content-type; bh=VqRnA7HO5MylUiy9aNvb3z7W27rieIef5zVnrQ0SuQw=; b=Y7l/4IhfYJaAFyK00p+sSvSa9TrSwuXtO9ThWaVY1E8YXwz+aEfcTdwAGZldbJxCL7 Mz+k7iEkv038g/P0QFYcf6YFaaFdYmfiaZyMJz1rvac0W8XBdVj2GM6FukEwBTgyLF+N rb652VJxjKR/YjC1px+sZvuhSJ0nBnxue0FUPzK6Lkx9YrPtI2Jz8IOe7MXxtQ4VkaYO sVrIGSGAU5BUTDWzUqNWxAToomsqQKiJU7yooR75p99HKASBhbOV9/5F5BSZ1okEVdp/ /+70xzmdX0KglzCdfQ+bJA4xcRh0HhHNhuqikQfbOQWTy9oKFQpi8tFd2OSLHXcG2JaO TFoQ== MIME-Version: 1.0 X-Received: by 10.107.160.141 with SMTP id j135mr23237485ioe.43.1432476003935; Sun, 24 May 2015 07:00:03 -0700 (PDT) In-Reply-To: <878uce2jh4.fsf@nautilus.nautilus> References: <87fv6ol93p.fsf@nautilus.nautilus> <20150522224229.GA62222@cskk.homeip.net> <878uce2jh4.fsf@nautilus.nautilus> Date: Mon, 25 May 2015 00:00:03 +1000 Subject: Re: Camelot a good tool for me From: Chris Angelico To: "python-list@python.org" Content-Type: text/plain; charset=UTF-8 X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.20+ Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 60 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1432476007 news.xs4all.nl 2932 [2001:888:2000:d::a6]:37169 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:91183 On Sun, May 24, 2015 at 11:28 PM, Lele Gaifax wrote: > Chris Angelico writes: > >> You don't automatically get nice objects with attributes named after >> columns, but neither will SQLAlchemy unless you're doing the >> equivalent of "select * from". Example: >> >>>>> session.query(Student).all() >> [<__main__.Student object at 0x7fc2de3fc290>, <__main__.Student object >> at 0x7fc2de3fc350>, <__main__.Student object at 0x7fc2de3fc3d0>] >> >> That's a list of Student objects, because I asked for the entire table. >> >>>>> session.query(Student.name, Student.year).all() >> [(u'Fred', 2015), (u'Joe', 2015), (u"Robert'); DROP TABLE Students;--", 2012)] >> >> That's a list of tuples, because I asked for just two columns. > > Wrong: > > >>> res = session.query(Student.name, Student.year).all() > >>> type(res) > > >>> type(res[0]) > > >>> type(res[0].name) > > >>> type(res[0][0]) > > >>> res[0].name == res[0][0] > True Huh. Okay, was not aware of that. It's some sort of namedtuple-like thing that acts as a tuple but has attributes too. Very nice. I withdraw the criticism. My other criticisms were mainly on the basis that bad code is easier to write when you have more magic; rebuttals of the form "but nobody would be dumb enough to write code like that" are valid only to the extent that poor programmers are more likely to be using PHP than Python, so we're seeing a better calibre of coder here. But it's still very much possible to see - and have to maintain - some pretty horrendous code. Someone chooses to iterate over the query rather than calling .all() because "it's quicker that way" (it may or may not be, given that iterating over the query is lazy but all() is eager), and then calls session.commit() every hundred rows because "it's quicker that way". I've seen both of the above, although not together and not in SQLAlchemy. The latter is quite common; check out these advice pages, which seem to consider committing to be something you do for performance reasons rather than to enforce transactional integrity: http://www.ajaxline.com/32-tips-to-speed-up-your-mysql-queries http://stackoverflow.com/questions/14675147/why-does-transaction-commit-improve-performance-so-much-with-php-mysql-innodb -- question asked "Would you recommend COMMIT'ing every 1,000 or so INSERTS's..." That thinking is out there, and if you don't keep your transactions clear and clean, you WILL have problems. ChrisA