当我从 SQL Server 代理运行 Python 脚本时,为啥它会失败?

Posted

技术标签:

【中文标题】当我从 SQL Server 代理运行 Python 脚本时,为啥它会失败?【英文标题】:Why does my Python script fail when I run it from SQL Server Agent?当我从 SQL Server 代理运行 Python 脚本时,为什么它会失败? 【发布时间】:2020-07-15 01:21:42 【问题描述】:

我有一个 Python 脚本,当我在 IDE 中运行它时它运行良好。如果我从命令行执行它,我必须在它所在的目录中才能正常运行。如果我尝试将其作为代理作业或使用 SSIS 中的执行流程任务运行它会失败。

代理作业中的脚本如下所示:

py E:\Opt\AppDirectory\foo.py
SET EXITCODE = %ERRORLEVEL% 
IF %EXITCODE% EQ 0 ( 
   REM Script Ran Sucessfully
   EXIT 0
)
IF %EXITCODE% EQ 1 (
    REM Script Error
    EXIT 1
)

当我运行它时,或者在 SSIS 中,我得到:

Traceback (most recent call last):
  File "E:\Opt\AppDirectory\foo.py", line 76, in <module>
    encoder = jl.load('model.joblib')
  File "C:\ProgramData\Anaconda3\lib\site-packages\joblib\numpy_pickle.py", line
 590, in load
    with open(filename, 'rb') as f:
FileNotFoundError: [Errno 2] No such file or directory: 'model.joblib'

model.joblib 与 foo.py 位于完全相同的目录中。当它说找不到文件时真的很奇怪,但我正盯着它。

job 可以找到 foo.py。为什么好像找不到model.joblib?

【问题讨论】:

请发帖minimal reproducible example。很可能 foo.py 脚本正在您当前的工作目录中运行,它只知道文件名,而不知道路径。在执行 python 脚本之前,您可以在批处理脚本中尝试cd %~p0 您知道您回答了自己的问题,对吧? “如果我从命令行执行它,我必须在它所在的目录中才能正常运行。” 换句话说,SQL 代理作业需要将目录更改为脚本在执行之前的位置。 @jwdonahue,这是复杂 NLP 过程的一部分,因此即使是可以复制的最小示例也是不可能的。但是,你确实给了我一个想法。我会试试你的方法。如果失败,我将使用绝对路径。 @AlwaysLearning 我确实尝试更改批处理脚本中的目录。它仍然不起作用,这是我变得比现在更加困惑的时候。当您在 IDE 中运行某些东西时,您是在文件所在的文件夹中运行它。所以我不知道代理在哪里运行脚本。 你能用脚本写一个日志文件吗?您可以转储整个环境和 cwd。或许能给你一些线索。我对该代理的工作原理一无所知,但它可能会为您的脚本提供非常有限的文件系统视图。您可能必须以某种方式“安装”您的文件或为其配置添加一些路径。除此之外,我的想法很新鲜。 【参考方案1】:

当你像你一样从 SQL SERVER 调用时,你需要将 sys.exit(0) 作为最后一件事。我遇到过很多次脚本执行良好但 SQL Server 代理失败的情况。

我的工作一直是将 XYZ 包装在一个函数中。在下面,您将得到除以零,以显示 sql server 会给您错误消息。如果你删除它 故意报错你会看到SQL server成功。

import sys

def test():
    try:
    
        x = 1/0
    
        if 1 > 0:
            return

    except BaseException as e:
        print(e)
        sys.exit(1)

test()
sys.exit(0)

继续检查它应该适用于您的:

py E:\Opt\AppDirectory\foo.py
SET EXITCODE = %ERRORLEVEL% 
IF %EXITCODE% EQ 0 ( 
   REM Script Ran Sucessfully
   EXIT 0
)
IF %EXITCODE% EQ 1 (
    REM Script Error
    EXIT 1
)

【讨论】:

这最终成为了一些微妙警告的答案:1. 这是一个权限问题。我正在使用代理。该凭据使用我的登录名。我是管理员。管理员可以完全控制目标文件夹,但我仍然必须将我的特定用户添加到文件夹权限中。 2.py 不工作。你必须在第一行实际使用 python。 好吧 py 就是我所拥有的别名,它必须是你系统上的任何东西。【参考方案2】:

这不是答案,但我将发布我现在所做的。这是在截止日期前为客户准备的,所以我只是一起拍了一些东西。几周后我会发布更深入的分析。

第一件事是我需要有一个指向 model.joblib 的绝对路径。那是我的错。我通常在 Jupyter Lab 工作,却忘记了这是必要的。

但是,这并没有完全解决问题。作业运行了,但它就像跳过执行奇怪的脚本一样。最终的解决方案是使用 SSIS 中的 Execute Process Task 来运行脚本,然后将代理作业从 CmdExec 更改为 SSIS 包,这样一切正常。

【讨论】:

好吧,你做到了,我在 sql server 作业中从 cmd 运行没有问题。这可能不适用于您的特定问题,但它涵盖了在 sql 作业中获取正确的失败/成功和错误消息。在我的情况下,它是为了避免 SSIS 开始并启动一个 py 脚本。 如果您可以正常运行但代理不能运行,这听起来像是对我的许可。

以上是关于当我从 SQL Server 代理运行 Python 脚本时,为啥它会失败?的主要内容,如果未能解决你的问题,请参考以下文章