Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kLEbF-0004NM-IZ for psycopg@arkaria.postgresql.org; Wed, 23 Sep 2020 23:55:02 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1kLEbC-0005Dp-Si for psycopg@arkaria.postgresql.org; Wed, 23 Sep 2020 23:54:58 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kLEbB-0005BB-43 for psycopg@lists.postgresql.org; Wed, 23 Sep 2020 23:54:58 +0000 Received: from wout5-smtp.messagingengine.com ([64.147.123.21]) by makus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kLEb3-0005Kt-Go for psycopg@lists.postgresql.org; Wed, 23 Sep 2020 23:54:55 +0000 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.west.internal (Postfix) with ESMTP id 9E32C9AF; Wed, 23 Sep 2020 19:54:46 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute4.internal (MEProxy); Wed, 23 Sep 2020 19:54:46 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aklaver.com; h= subject:to:references:from:message-id:date:mime-version :in-reply-to:content-type:content-transfer-encoding; s=fm1; bh=v SokEV+ve5QtwiEcDCn6EhnvXasWdms3R5uCqT3y3Q4=; b=EwHYMl88gjwZGGHNk YI+7/Pc5IR6ZC4fVGZuJ+cvsCQ+eultIdpX970vpKHLY3jT67xP6x4AjMq5TlrHm IwLK1rvq/aaZVnmuL/IL7de+1fQBd0quch2hoZi0dc5EyU7lZpe9HegVMg6YA/er riD4y60Us5V2MkglGE6F0as7KXvdbyJ4KRwxIRDKvkkRV9o1RaFeEDEc0VOoi69h KrFPaURHUANxZebznfguSBRAb/g69KpDmFPZRHv+I2MKiogmHcmYKluNuHuWmWG9 Ah7CFYKsMeWraIGnB+3WhUwKhsjobU+Qr26db2Q18ygoikAu1D0glZCJSoyF1KFc zAN9A== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=content-transfer-encoding:content-type :date:from:in-reply-to:message-id:mime-version:references :subject:to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender :x-sasl-enc; s=fm3; bh=vSokEV+ve5QtwiEcDCn6EhnvXasWdms3R5uCqT3y3 Q4=; b=rqWb4oI19DeizR/8E71CIrD3cRmHEyR/L3MbtAxXgBvR2LgCbQCd7pO3B 0//xXPtrpbxjRbiZVaBbXtDYYq4fPDWmzW+wyvRFboRPoEpUCX7NhLswerVA2oKt nEq9tBslFiKZApB0R2Tiu0EHl2FKh6xUvdlvQac5sTv7rcAgbQxwa+FUC64TDRo1 dBgvd5SlaBKpcRn5uBRBEfkD6dKinfhRBbVXZu1dHSiDrQScaF2fLUMKV/13q2bZ Q+RS2azKrxt7gIwEG2d0H0kQLpYNQ06u/5F2rE/lJQIp9Y8e9xfWBb52p2y/Xrj1 TNttPBFkAAHt8ngaQ8Aye7SydzKFw== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedujedrudejgddvhecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenuc fjughrpefuvfhfhffkffgfgggjtgfgsehtjeertddtfeejnecuhfhrohhmpeetughrihgr nhcumfhlrghvvghruceorggurhhirghnrdhklhgrvhgvrhesrghklhgrvhgvrhdrtghomh eqnecuggftrfgrthhtvghrnhepteejvdetffejuedvleeifeefheeutdfhgfdvhffhhfek vdduveegvdejudefgfevnecukfhppeejhedrudejvddrhedrvdefudenucevlhhushhtvg hrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrughrihgrnhdrkhhlrghv vghrsegrkhhlrghvvghrrdgtohhm X-ME-Proxy: Received: from [192.168.1.3] (75-172-5-231.tukw.qwest.net [75.172.5.231]) by mail.messagingengine.com (Postfix) with ESMTPA id 99B5A3064674; Wed, 23 Sep 2020 19:54:45 -0400 (EDT) Subject: Re: iterating over DictRow To: Karsten Hilbert , psycopg@lists.postgresql.org References: <20200923215444.GA25406@hermes.hilbert.loc> From: Adrian Klaver Message-ID: <27c3e20a-3ff8-28a7-b16b-4d052628f02d@aklaver.com> Date: Wed, 23 Sep 2020 16:54:44 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.12.0 MIME-Version: 1.0 In-Reply-To: <20200923215444.GA25406@hermes.hilbert.loc> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk On 9/23/20 2:54 PM, Karsten Hilbert wrote: > Dear all, > > I cannot currently wrap my head around why I am seeing this: > > 2020-09-23 23:30:23 gmConnectionPool.py::() #87): psycopg2 module version: 2.8.5 (dt dec pq3 ext) > 2020-09-23 23:30:23 gmConnectionPool.py::() #88): PostgreSQL via DB-API module "": API level 2.0, thread safety 2, parameter style "pyformat" > 2020-09-23 23:30:23 gmConnectionPool.py::() #89): libpq version (compiled in): 120002 > 2020-09-23 23:30:23 gmConnectionPool.py::() #90): libpq version (loaded now) : 120004 > ... > 2020-09-23 23:30:28 gmConnectionPool.py::__log_on_first_contact() #445): heed Prime Directive > 2020-09-23 23:30:28 gmConnectionPool.py::__log_on_first_contact() #457): PostgreSQL version (numeric): 11.7 > ... > 2020-09-23 23:31:02 gmMacro.py::_get_variant_diagnoses() #2442): [[260, 'L: Bewegungsapparat', False, 'B', 'clin.health_issue'], [260, 'K: aHT/HI', False, 'B', 'clin.health_issue'], [260, 'D: Verdauung', False, None, 'clin.health_issue']] > 2020-09-23 23:31:02 gmMacro.py::_get_variant_diagnoses() #2443): > 2020-09-23 23:31:02 gmMacro.py::_escape_dict() #2851): 260 > 2020-09-23 23:31:02 gmMacro.py::__getitem__() #880): placeholder handling error: diagnoses:: \item %(diagnosis)s:: > Traceback (most recent call last): > File "/home/ncq/Projekte/gm/git/gnumed/gnumed/Gnumed/wxpython/gmMacro.py", line 869, in __getitem__ > val = handler(data = options) > File "/home/ncq/Projekte/gm/git/gnumed/gnumed/Gnumed/wxpython/gmMacro.py", line 2445, in _get_variant_diagnoses > return '\n'.join(template % self._escape_dict(dx, none_string = '?', bool_strings = [_('yes'), _('no')]) for dx in selected) > File "/home/ncq/Projekte/gm/git/gnumed/gnumed/Gnumed/wxpython/gmMacro.py", line 2445, in > return '\n'.join(template % self._escape_dict(dx, none_string = '?', bool_strings = [_('yes'), _('no')]) for dx in selected) > File "/home/ncq/Projekte/gm/git/gnumed/gnumed/Gnumed/wxpython/gmMacro.py", line 2852, in _escape_dict > val = the_dict[field] > File "/usr/lib/python3/dist-packages/psycopg2/extras.py", line 169, in __getitem__ > return super(DictRow, self).__getitem__(x) > IndexError: list index out of range > > This line logs a list of DictRow's: > > 2020-09-23 23:31:02 gmMacro.py::_get_variant_diagnoses() #2442): [[260, 'L: Bewegungsapparat', False, 'B', 'clin.health_issue'], [260, 'K: aHT/HI', False, 'B', 'clin.health_issue'], [260, 'D: Verdauung', False, None, 'clin.health_issue']] > > as evidenced here: > > 2020-09-23 23:31:02 gmMacro.py::_get_variant_diagnoses() #2443): > > The logging code: > > _log.debug('%s', selected) > _log.debug('%s', type(selected[0])) > > and then iterates over the list of DictRow's as per list > comprehension like so: > > return '\n'.join(template % self._escape_dict(dx, none_string = '?', bool_strings = [_('yes'), _('no')]) for dx in selected) > > where _escape_dict() does this: > > def _escape_dict(self, the_dict=None, date_format='%Y %b %d %H:%M', none_string='', bool_strings=None): > data = {} > for field in the_dict: > _log.debug('%s', field) > val = the_dict[field] > if val is None: > ... > if isinstance(val, bool): > ... > if isinstance(val, datetime.datetime): > ... > if self.__esc_style in ['latex', 'tex']: > ... > elif self.__esc_style in ['xetex', 'xelatex']: > ... > return data > > Iterating over the_dict should work for lists (produces > values) OR dicts (produces keys, under py3). It seems as if > the line > > for field in the_dict: # I hoped to iterate over the keys = column names > > somehow "decides": "currently we are treating the_dict as a > list (after all, it is a DictRow, which _can_ be treated as a > list) which then "turns" the dict-style access in > > val = the_dict[field] > > into a list access. > > Somehow I have a feeling that due to the type of "field" > -- it being integer (namely, a primary key) -- forces > > the_dict[field] > > to attempt a list-style index based access (which fails, due > to there not being 260 columns in the SQL query result :-) > > Solutions that come to mind: > > _Must_ I use RealDictCursor() to safely avoid this trap ? > > (or else dict()ify DictRow's as needed) > > Any insights to be had ? Maybe?: con = psycopg2.connect("dbname=production host=localhost user=postgres", cursor_factory=DictCursor) cur = con.cursor() cur.execute("select * from cell_per") the_dict = cur.fetchall() # Example 1 for row in the_dict: for fld in row: print(fld) # Return just field values ... 4 HERB 3.5 19 None 2020-09-22 17:34:31 None postgres herb none HR3 #Example 2 for row in the_dict: for fld in dict(row): print(fld, row[fld]) Showing the field name and field value. ... line_id 4 category HERB 3.5 cell_per 19 ts_insert None ts_update 2020-09-22 17:34:31 user_insert None user_update postgres plant_type herb season none short_category HR3 > > Thanks, > Karsten > -- > GPG 40BE 5B0E C98E 1713 AFA6 5BC0 3BEA AC80 7D4F C89B > > -- Adrian Klaver adrian.klaver@aklaver.com