如何在Python和postgresql中使用inet类型?

时间:2011-05-17 04:51:55

标签: python postgresql inet

我正在编写一个使用postgresql数据库的python3程序,我使用py-postgresql:http://python.projects.postgresql.org/作为数据库驱动程序。 一个表使用inet类型存储IP地址。

我创建了以下准备好的声明:

aID = db.prepare('SELECT id FROM a_records WHERE ip = $1 LIMIT 1')

调用aID(ip)时出现以下错误:

(ip是一个python字符串)

 File "/usr/local/lib/python3.1/dist-packages/postgresql/driver/pq3.py", line
1517, in __call__
    c = SingleXactFetch(self, parameters)
  File "/usr/local/lib/python3.1/dist-packages/postgresql/driver/pq3.py", line
837, in __init__
    Output.__init__(self, '')
  File "/usr/local/lib/python3.1/dist-packages/postgresql/driver/pq3.py", line
622, in __init__
    self._init()
  File "/usr/local/lib/python3.1/dist-packages/postgresql/driver/pq3.py", line
854, in _init
    STEP()
  File "/usr/local/lib/python3.1/dist-packages/postgresql/driver/pq3.py", line
2612, in _pq_step
    self.typio.raise_error(x.error_message, cause = getattr(x, 'exception', Non
e))
  File "/usr/local/lib/python3.1/dist-packages/postgresql/driver/pq3.py", line
507, in raise_error
    self.raise_server_error(error_message, **kw)
  File "/usr/local/lib/python3.1/dist-packages/postgresql/driver/pq3.py", line
498, in raise_server_error
    raise server_error
postgresql.exceptions.BinaryRepresentationError: invalid address family in exte
rnal "inet" value
  CODE: 22P03
  LOCATION: File 'network.c', line 218, in network_recv from SERVER
RESULT:
  type: SingleXactFetch
  parameters: ('139.78.113.1',)
STATEMENT: [prepared]
  sql_parameter_types: ['pg_catalog.inet']
  results: (id INTEGER)
  statement_id: py:0x2ff9a50
  string: SELECT id FROM a_records WHERE ip = $1 LIMIT 1
CONNECTION: [idle]
  client_address: 127.0.0.1/32
  client_port: 51563
  version:
    PostgreSQL 8.4.7 on x86_64-pc-linux-gnu, compiled by GCC gcc-4.4.real (Debi
an 4.4.5-8) 4.4.5, 64-bit
CONNECTOR: [IP4] pq://python:***@127.0.0.1:5432/vdz
  category: None
DRIVER: postgresql.driver.pq3.Driver

任何人都可以帮我调试这个并弄清楚为什么postgresql不喜欢inet数据吗?

谢谢!

3 个答案:

答案 0 :(得分:1)

我整天都遇到这个问题,而且我找不到任何解决方案,所以很明显我在发布这里后几分钟就找到了解决方案。

我需要用inet($ 1 :: varchar)替换$ 1,似乎postgresql在转换为inet值时不喜欢它是一个字符串,你必须将它作为varchar进行类型转换,然后将值转换为一个inet变量。

所以,工作线是:

aID = db.prepare('SELECT id FROM a_records WHERE ip = inet($1::varchar) LIMIT 1')

任何人都可以解释为什么会这样,以及为什么它不会像我最初尝试的那样工作?

谢谢!

答案 1 :(得分:1)

@mrlanrat,这是因为python库将您的参数作为TEXT数据类型发送,但PostgreSQL期望INET数据类型。您的示例更改了参数,以便PostgreSQL期望TEXT数据类型,然后将其转换为INET数据类型。我知道psycopg2支持INET数据类型,但我很确定当前版本的py-postgresql不支持数据类型(截至2011-05-19)。这意味着您有三种选择:

  1. py-postgresql需要添加对INET数据类型的支持
  2. 您可以传入TEXT类型的数据,然后将其转发到服务器上的INET
  3. 切换到psycopg2,它支持INET数据类型。
  4. http://initd.org/psycopg/docs/extras.html#inet-data-type

答案 2 :(得分:0)

您应该显式地将字符串转换为inet数据类型。

aID = db.prepare('SELECT id FROM a_records WHERE ip = inet($1) LIMIT 1')