当我从 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 脚本时,为啥它会失败?的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server LEFT OUTER JOIN 查询性能

vb.net 运行 gpg.exe 作业步骤从 PC 运行正常,但不能从 SQL Server 代理计划运行

从提示符运行 powershell 脚本时,SQL Server 2008 不使用备份设备路径

SQL Server 代理作业不执行 SSIS 包权限错误

SQL Server代理(10/12):使用代理账号运行作业

无法在 sql server 代理中运行作业