Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使python等待存储过程完成执行_Python_Sql_Sql Server_Stored Procedures_Pyodbc - Fatal编程技术网

使python等待存储过程完成执行

使python等待存储过程完成执行,python,sql,sql-server,stored-procedures,pyodbc,Python,Sql,Sql Server,Stored Procedures,Pyodbc,我有一个python脚本,它使用pyodbc调用MSSQL存储过程,如下所示: cursor.execute("exec MyProcedure @param1 = '" + myparam + "'") 我在一个循环中调用这个存储过程,我注意到有时,在上次执行完成之前,该过程会再次被调用。我知道这一点,因为如果我添加行 time.sleep(1) 执行行之后,一切正常 有没有一种更优雅、花费更少时间的方式来表达“睡到执行官结束” 更新(Divij的解决方案):此代码目前不适用于我: fro

我有一个python脚本,它使用pyodbc调用MSSQL存储过程,如下所示:

cursor.execute("exec MyProcedure @param1 = '" + myparam + "'")
我在一个循环中调用这个存储过程,我注意到有时,在上次执行完成之前,该过程会再次被调用。我知道这一点,因为如果我添加行

time.sleep(1)
执行行之后,一切正常

有没有一种更优雅、花费更少时间的方式来表达“睡到执行官结束”

更新(Divij的解决方案):此代码目前不适用于我:

from tornado import gen
import pyodbc

@gen.engine
def func(*args, **kwargs):
    # connect to db
    cnxn_str = """
    Driver={SQL Server Native Client 11.0};
    Server=172.16.111.235\SQLEXPRESS;
    Database=CellTestData2;
    UID=sa;
    PWD=Welcome!;
    """
    cnxn = pyodbc.connect(cnxn_str)
    cnxn.autocommit = True
    cursor = cnxn.cursor()
    for _ in range(5):
        yield gen.Task(cursor.execute, 'exec longtest')

    return

func()

没有内置python允许您等待异步调用完成。然而,您可以使用Tornado的iLoop实现这种行为。Tornado的
gen
界面允许您将函数调用注册为
任务
,并在调用完成后返回函数中的下一行。下面是一个使用
gen
gen.Task

来自tornado导入gen的

@发电机
def func(*args,**kwargs)
对于范围(5)内的uu:
生成gen.Task(异步函数调用,arg1,arg2)
返回
在本例中,
func
的执行在
async\u function\u调用
完成后恢复。这样,对
asnyc\u函数的后续调用不会重叠,并且您不必在
时间内暂停主进程的执行。sleep
调用。

以下是我的解决方法:

在数据库中,我创建了一个名为
RunningStatus
的表,其中只有一个字段
status
,它是一个
位,只有一行,最初设置为0

在存储过程开始时,我执行

update RunningStatus set status = 1;
在存储过程的末尾

update RunningStatus set status = 0;
在我的Python脚本中,我打开了一个新连接,并将光标指向同一个数据库。在我的
execute
行之后,我只需添加

while 1:
    q = status_check_cursor.execute('select status from RunningStatus').fetchone()
    if q[0] == 0:
        break
您需要建立一个新连接和游标,因为来自旧连接的任何调用都将中断存储过程,并可能导致
status
永远不会返回0


这有点刺耳,但对我来说效果很好

我认为我的方法有点粗糙,但同时也更容易理解:

cursor = connection.cursor()
    SQLCommand = ("IF EXISTS(SELECT 1 FROM msdb.dbo.sysjobs J JOIN 
msdb.dbo.sysjobactivity A ON A.job_id = J.job_id WHERE J.name ='dbo.SPNAME' AND 
A.run_requested_date IS NOT NULL AND A.stop_execution_date IS NULL) select 'The job is 
running!' ELSE select 'The job is not running.'")
    cursor.execute(SQLCommand)
    results = cursor.fetchone()
    sresult= str(results)
    while "The job is not running" in sresult:
        time.sleep(1)
        cursor.execute(SQLCommand)
        results = cursor.fetchone()
        sresult= str(results)
当“SPNAME”从jobactivity表返回“作业未运行”时,请休眠1秒并再次检查结果。
这个sql作业的工作,对于SP,应该像在另一个表中一样

我知道这很旧,但我只是花了几个小时试图弄清楚如何让Python代码等待MSSQL上的存储过程完成

问题不在于异步调用

解决此问题的关键是确保过程在完成运行之前不会返回任何消息。否则,PYDOBC将来自proc的第一条消息解释为它的结束

使用
设置NOCOUNT ON
运行您的过程。另外,确保可能用于调试的任何
PRINT
语句或
RAISERROR
都已禁用

在进程中添加一个位参数,如
@muted
,只有当它是
0
时才会引发调试消息

在我的特殊情况下,我正在执行一个proc来处理一个加载的表,而我的应用程序在该过程完成运行之前正在退出并关闭游标,因为我正在获取行计数和调试消息

总结一下,按照

cursor.execute('SET NOCOUNT ON;EXEC schema.proc@muted=1')


PYODBC将等待进程完成。

谢谢您的回答!我正在阅读tornado.gen文档,对于任务函数如何与pyodbc光标一起工作,我有点困惑。对
cursor.execute
的调用是作为
async\u function\u call
的一部分包含的,还是在没有pyodbc的情况下执行存储过程?如果是后者,它如何连接到数据库?理想情况下,您可以将
异步函数调用
替换为
游标。执行
并将要执行的过程作为参数传递。因此,您的行应该是:
yield gen.Task(cursor.execute,“exec MyProcedure@param1'%s'”%myparam)
我尝试了这个确切的示例,但它给了我
TypeError:execute()不接受关键字参数
。它对您是否正常工作?嗯,您能将代码中出现错误的那一行粘贴到这里吗?另外,由于要执行的命令涉及字符串插值,因此我会尝试先将命令存储为变量,然后将变量作为参数传递。我制作了一个测试python脚本,该脚本仅连接到MSSQL数据库,然后执行您答案中的确切代码。我创建了一个名为
longtest
的存储过程,它基本上只是循环并多次递增计数器。我在行中得到错误,
yield gen.Task(cursor.execute,'exec longtest')
。有什么想法吗?太棒了<代码>设置不计数
保存了我的一天!如果存储过程保证在没有错误的情况下运行,这是非常好的,但是如果存储过程在执行过程中可能出错,请小心。如果从未将状态设置回0,则会导致Python脚本中出现无限循环。