teradatasql Python 模块仅在编写脚本时有效,但在 运行 代码时无效

teradatasql Python module only works when scripting but not when running code

我在使用 teradatasql 包(从 pypi 安装)时遇到了一个特殊问题 运行。我使用以下代码(我们称之为 pytera.py)来查询数据库:

from dotenv import load_dotenv
import pandas as pd
import teradatasql

# Load the database credentials from .env file
_ = load_dotenv()
db_host = os.getenv('db_host')
db_username = os.getenv('db_username')
db_password = os.getenv('db_password')


def run_query(query):
    """Run query string on teradata and return DataFrame."""
    if query.strip()[-1] != ';':
        query += ';'

    with teradatasql.connect(host=db_host, user=db_username,
                         password=db_password) as connect:
        df = pd.read_sql(query, connect)
    return df

当我在 IPython/Python 解释器或 Jupyter Notebook 中导入此函数时,我可以 运行 查询就像这样:

import pytera as pt

pt.run_query('select top 5 * from table_name;')

但是,如果我将上面的代码保存在一个 .py 文件中并尝试 运行 它,大多数时候(不是所有时候)我都会收到一条错误消息。错误信息如下。

E   teradatasql.OperationalError: [Version 16.20.0.49] [Session 0] [Teradata SQL Driver] Hostname lookup failed for None
E    at gosqldriver/teradatasql.(*teradataConnection).makeDriverError TeradataConnection.go:1046
E    at gosqldriver/teradatasql.(*Lookup).getAddresses CopDiscovery.go:65
E    at gosqldriver/teradatasql.discoverCops CopDiscovery.go:137
E    at gosqldriver/teradatasql.newTeradataConnection TeradataConnection.go:133
E    at gosqldriver/teradatasql.(*teradataDriver).Open TeradataDriver.go:32
E    at database/sql.dsnConnector.Connect sql.go:600
E    at database/sql.(*DB).conn sql.go:1103
E    at database/sql.(*DB).Conn sql.go:1619
E    at main.goCreateConnection goside.go:229
E    at main._cgoexpwrap_e6e101e164fa_goCreateConnection _cgo_gotypes.go:214
E    at runtime.call64 asm_amd64.s:574
E    at runtime.cgocallbackg1 cgocall.go:316
E    at runtime.cgocallbackg cgocall.go:194
E    at runtime.cgocallback_gofunc asm_amd64.s:826
E    at runtime.goexit asm_amd64.s:2361
E   Caused by lookup None on <ip address redacted>: server misbehaving

我在 Ubuntu (WSL) 18.04 上使用 Python 3.7.3 和 teradatasql 16.20.0.49。

也许并非巧合,我 运行 在 Windows 上尝试类似的工作流程时遇到了类似的问题(使用 teradata 包和安装的 Teradata Python 驱动程序)。当我在解释器内部或 Jupyter 中连接时有效,但在脚本中无效。在Windows的情况下,错误是:

E teradata.api.DatabaseError: (10380, '[08001] [Teradata][ODBC] (10380) Unable to establish connection with data source. Missing settings: {[DBCName]}')

我觉得我缺少一些基本的东西,但我找不到解决这个问题的任何地方。

您的客户端似乎找不到 Teradata 服务器,这就是您看到 DBCName 丢失错误的原因。这应该是您的 Teradata 服务器的 "system name"(即 TDServProdA)。

有几件事要尝试:

  1. 如果您尝试直接使用主机名连接,请尝试使用此标志在您的连接中禁用 COP 发现:cop = falseMore info

  2. 尝试更新本地系统上的 hosts 文件。来自文档:

Modifying the hosts File

If your site does not use DNS, you must define the IP address and the Teradata Database name to use in the system hosts file on the computer.

  1. Locate the hosts file on the computer. This file is typically located in the following folder: %SystemRoot%\system32\drivers\etc
  2. Open the file with a text editor, such as Notepad.
  3. Add the following entry to the file: xxx.xx.xxx.xxx sssCOP1 where xxx.xx.xxx.xxx is the IP address and where sss is the Teradata Database name.

  4. Save the hosts file.

Link 1
Link 2

感谢 带来新鲜的目光。原来问题是使用 dotenv 加载环境变量。我的模块在 Python 包(单独的文件夹)中,我的脚本和 .env 文件在工作目录中。

dotenv 在我 运行 原始 post 中的代码时,在解释器或 Jupyter 中逐行读取环境变量(我的工作目录中的 .env)。但是,当我 运行 在脚本中使用相同的代码时,它在我的工作目录的 .env 文件中找不到。那将是一个单独的问题,我必须找到答案。

import teradatasql
import pandas as pd


def run_query(query, db_host, db_username, db_password):
    """Run query string on teradata and return DataFrame."""
    if query.strip()[-1] != ';':
        query += ';'

    with teradatasql.connect(host=db_host, user=db_username,
                         password=db_password) as connect:
        df = pd.read_sql(query, connect)
    return df

下面的代码 运行 现在可以在脚本中使用:

import pytera as pt
from dotenv import load_dotenv()

_ = load_dotenv()
db_host = os.getenv('db_host')
db_username = os.getenv('db_username')
db_password = os.getenv('db_password')

data = pt.run_query('select top 5 * from table_name;', db_host, db_username, db_password)