使用 SQLAlchemy 和多处理挂入 Python 脚本

2023-11-22

考虑以下 Python 脚本,它使用 SQLAlchemy 和 Python 多处理模块。 这是 Debian squeeze 上的 Python 2.6.6-8+b1(默认)和 SQLAlchemy 0.6.3-3(默认)。 这是一些实际代码的简化版本。

import multiprocessing
from sqlalchemy import *
from sqlalchemy.orm import *
dbuser = ...
password = ...
dbname = ...
dbstring = "postgresql://%s:%s@localhost:5432/%s"%(dbuser, password, dbname)
db = create_engine(dbstring)
m = MetaData(db)

def make_foo(i):
    t1 = Table('foo%s'%i, m, Column('a', Integer, primary_key=True))

conn = db.connect()
for i in range(10):
    conn.execute("DROP TABLE IF EXISTS foo%s"%i)
conn.close()
db.dispose()

for i in range(10):
    make_foo(i)

m.create_all()

def do(kwargs):
    i, dbstring = kwargs['i'], kwargs['dbstring']

    db = create_engine(dbstring)
    Session = scoped_session(sessionmaker())
    Session.configure(bind=db)
    Session.execute("COMMIT; BEGIN; TRUNCATE foo%s; COMMIT;")
    Session.commit()
    db.dispose()

pool = multiprocessing.Pool(processes=5)               # start 4 worker processes
results = []
arglist = []
for i in range(10):
    arglist.append({'i':i, 'dbstring':dbstring})
r = pool.map_async(do, arglist, callback=results.append) # evaluate "f(10)" asynchronously
r.get()
r.wait()
pool.close()
pool.join()

该脚本挂起并显示以下错误消息。

Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/lib/python2.6/threading.py", line 532, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.6/threading.py", line 484, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/usr/lib/python2.6/multiprocessing/pool.py", line 259, in _handle_results
    task = get()
TypeError: ('__init__() takes at least 4 arguments (2 given)', <class 'sqlalchemy.exc.ProgrammingError'>, ('(ProgrammingError) syntax error at or near "%"\nLINE 1: COMMIT; BEGIN; TRUNCATE foo%s; COMMIT;\n        ^\n',))

当然,这里的语法错误是TRUNCATE foo%s;。我的问题是,为什么进程挂起,我可以说服它以错误退出,而不对我的代码进行重大修改吗?此行为与我的实际代码非常相似。

请注意,如果该语句被替换为类似的内容,则不会发生挂起print foobarbaz。另外,如果我们更换,挂起仍然会发生

Session.execute("COMMIT; BEGIN; TRUNCATE foo%s; COMMIT;")
Session.commit()
db.dispose()

by just Session.execute("TRUNCATE foo%s;")

我使用前一个版本,因为它更接近我的实际代码正在执行的操作。

另外,删除multiprocessing从图片中并连续循环遍历表格可以使挂起消失,并且它只是以错误退出。

我也对错误的形式感到困惑,特别是TypeError: ('__init__() takes at least 4 arguments (2 given)'少量。这个错误从何而来?看起来很可能是来自于某个地方multiprocessing code.

PostgreSQL 日志没有帮助。我看到很多像这样的行

2012-01-09 14:16:34.174 IST [7810] 4f0aa96a.1e82/1 12/583 0 ERROR:  syntax error at or near "%" at character 28
2012-01-09 14:16:34.175 IST [7810] 4f0aa96a.1e82/2 12/583 0 STATEMENT:  COMMIT; BEGIN; TRUNCATE foo%s; COMMIT;

但似乎没有其他相关的事情。

更新1:感谢lbolla和他的富有洞察力的分析,我能够提交Python 错误报告对这个。 看sbt该报告中的分析,以及here。另请参阅 Python 错误报告修复酸洗异常。因此,根据 sbt 的解释,我们可以重现原始错误

import sqlalchemy.exc
e = sqlalchemy.exc.ProgrammingError("", {}, None)
type(e)(*e.args)

这使

Traceback (most recent call last):
  File "<stdin>", line 9, in <module>
TypeError: __init__() takes at least 4 arguments (2 given)

更新 2:至少对于 SQLAlchemy,Mike Bayer 已修复此问题,请参阅错误报告StatementError 异常不可选取。。根据 Mike 的建议,我也向 psycopg2 报告了一个类似的错误,尽管我没有(也没有)有实际的损坏示例。无论如何,他们显然已经修复了这个问题,尽管他们没有提供修复的细节。看psycopg 异常无法被 pickle。为了更好地衡量,我还报告了一个 Python bugConfigParser 异常不可 pickle对应于lbolla提到的SO问题。看来他们想对此进行测试。

无论如何,这看起来在可预见的将来仍然会是一个问题,因为总的来说,Python 开发人员似乎没有意识到这个问题,因此也没有提防它。令人惊讶的是,似乎没有足够多的人使用多处理,因此这成为一个众所周知的问题,或者也许他们只是忍受它。我希望 Python 开发人员能够至少在 Python 3 中修复它,因为它很烦人。

我接受了 lbolla 的回答,因为如果没有他解释问题如何与异常处理相关,我可能无法理解这一点。我还要感谢 sbt,他解释说 Python 无法 pickle 异常是问题所在。我非常感谢他们俩,请投票支持他们的答案。谢谢。

更新 3:我发布了一个后续问题:捕获无法处理的异常并重新加注.


我相信TypeError来自multiprocessing's get.

我已经从您的脚本中删除了所有数据库代码。看看这个:

import multiprocessing
import sqlalchemy.exc

def do(kwargs):
    i = kwargs['i']
    print i
    raise sqlalchemy.exc.ProgrammingError("", {}, None)
    return i


pool = multiprocessing.Pool(processes=5)               # start 4 worker processes
results = []
arglist = []
for i in range(10):
    arglist.append({'i':i})
r = pool.map_async(do, arglist, callback=results.append) # evaluate "f(10)" asynchronously

# Use get or wait?
# r.get()
r.wait()

pool.close()
pool.join()
print results

Using r.wait返回预期的结果,但使用r.get raises TypeError。如中所述python 的文档, use r.wait之后map_async.

Edit: 我必须修改我之前的答案。我现在相信TypeError来自 SQLAlchemy。我修改了我的脚本以重现该错误。

Edit 2: 看来问题是这样的multiprocessing.pool如果任何工作人员引发其构造函数需要参数的异常,则效果不佳(另请参阅here).

我修改了我的脚本以突出这一点。

import multiprocessing

class BadExc(Exception):
    def __init__(self, a):
        '''Non-optional param in the constructor.'''
        self.a = a

class GoodExc(Exception):
    def __init__(self, a=None):
        '''Optional param in the constructor.'''
        self.a = a

def do(kwargs):
    i = kwargs['i']
    print i
    raise BadExc('a')
    # raise GoodExc('a')
    return i

pool = multiprocessing.Pool(processes=5)
results = []
arglist = []
for i in range(10):
    arglist.append({'i':i})
r = pool.map_async(do, arglist, callback=results.append)
try:
    # set a timeout in order to be able to catch C-c
    r.get(1e100)
except KeyboardInterrupt:
    pass
print results

在您的情况下,考虑到您的代码引发了 SQLAlchemy 异常,我能想到的唯一解决方案是捕获do功能并重新提高正常Exception反而。像这样的东西:

import multiprocessing

class BadExc(Exception):
    def __init__(self, a):
        '''Non-optional param in the constructor.'''
        self.a = a

def do(kwargs):
    try:
        i = kwargs['i']
        print i
        raise BadExc('a')
        return i
    except Exception as e:
        raise Exception(repr(e))

pool = multiprocessing.Pool(processes=5)
results = []
arglist = []
for i in range(10):
    arglist.append({'i':i})
r = pool.map_async(do, arglist, callback=results.append)
try:
    # set a timeout in order to be able to catch C-c
    r.get(1e100)
except KeyboardInterrupt:
    pass
print results

Edit 3: 所以,这似乎是一个Python 的错误,但是 SQLAlchemy 中的适当异常可以解决它:因此,我已经使用 SQLAlchemy 提出问题, too.

作为解决问题的方法,我认为最后的解决方案Edit 2会做(将回调包装在 try-except 中并重新引发)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 SQLAlchemy 和多处理挂入 Python 脚本 的相关文章

随机推荐

  • 我可以在gdb下打印gdtr和gdt描述符吗?

    I want to use gdb to see my GDTR LDTR TTR and segment register 不可见部分 x86 所以在 gdb 中我输入 p x gdtr 等 但结果是 6 值无法转换为整数 在 gdb 中
  • C 和 C++ 编码标准

    关于 C 和 C 编码标准的最佳实践是什么 是否应该允许开发人员随意将它们混合在一起 链接 C 和 C 目标文件时是否存在任何复杂情况 像传统上用 C 编写的套接字库之类的东西是否应该保留在 C 中并保存在单独的源文件中 即将 c 代码保存
  • Django CSRF 检查因 Ajax POST 请求而失败

    我可以通过我的 AJAX 帖子获得一些遵守 Django 的 CSRF 保护机制的帮助 我已按照此处的说明进行操作 http docs djangoproject com en dev ref contrib csrf 我已经准确地复制了该
  • ARKit 1.5 如何获取垂直平面的旋转

    我正在尝试垂直平面 并尝试将节点放置在墙上 并根据该垂直平面进行正确的旋转 这是被点击的垂直平面的 ARHitTestResult let hitLocation sceneView hitTest touchPoint types exi
  • 在没有互联网连接的计算机上使用 Scala

    我是 Scala 新手 如果问题绝对显而易见 我很抱歉 我的计算机上安装了 Eclipse Photon 想要编辑 Scala 代码并生成可运行的 jar 棘手的部分是我的计算机 Centos7 无法访问互联网 我记住两个潜在的问题 手动下
  • 如何在具有角度嵌套数据组的材料表中显示拆分标题

    当数据作为对象的嵌套数组出现时 我在材料表中显示数据时遇到问题 我想显示当前显示在 stackblitz 中的表格 如果我用我的更改现有数据newData变量它将开始破坏整个表 谁能指导我如何通过材料表中的一组嵌套数据实现拆分标题功能 我想
  • iPad 上具有自定义尺寸的 SwiftUI Sheet() 模式

    如何使用 SwiftUI 控制 iPad 上模态表的首选演示大小 我很惊讶在谷歌上找到这个问题的答案是多么困难 另外 了解模式是否通过向下拖动 取消 或实际执行自定义积极操作来关闭的最佳方法是什么 以下是我在 iPad 上使用 SwiftU
  • 找出两个缺失的数字

    我们有一台内存为 O 1 的机器 我们想要通过n第一遍中的数字 一个接一个 然后我们排除这两个数字 我们将通过n 2号码到机器 编写一个算法来查找缺失的数字 可以使用 O 1 内存来完成 您只需要几个整数来跟踪一些运行总和 整数不需要 lo
  • Autofac 和 ASP .Net MVC 4 Web API

    我在用Autofac用于我的 ASP Net MVC 4 项目中的 IoC Autofac 在初始化存储库并将其传递到API控制器 我确信我的配置中缺少某些内容 这是我导航到时遇到的错误 https localhost 44305 api
  • 在 Android 上强制执行 Expo 上的 LTR

    我正在使用 React Native 和 Expo 创建一个应用程序 但找不到强制 LTR 从左到右 方向的解决方案 我的一些用户的手机支持 RTL 语言 但我只有英语和挪威语 因此以英语显示 RTL 文本没有意义 我也使用 i18next
  • DbContext配置?

    数据库上下文 public class HaberPortalDB DbContext public DbSet
  • 有没有办法在 Visual Studio 2010 中突出显示当前活动的代码块?

    在 Visual Studio 2010 中 如果将鼠标悬停在小 减号上 它将突出显示该代码块 我的问题是 有没有办法让您在其中编码时始终突出显示该块 这样 当我在方法和类之间跳转时 我当前正在处理的任何块都会突出显示 以帮助我的眼睛快速聚
  • Angular Access ng-template 的内部组件

    假设我们有一个名为TopComponent使用这样的模板
  • 在 .CSS 文件中创建一个变量以在该 .CSS 文件中使用[重复]

    这个问题在这里已经有答案了 可能的重复 避免 CSS 中重复的常量 我们有一些在 CSS 表中重复使用的 主题颜色 有没有办法设置一个变量然后重用它 E g css OurColor Blue H1 color OurColor 不要求选择
  • 相当于 Python 的列表排序和 key / Schwartzian 变换

    在 Python 中 给定一个列表 我可以按关键函数对其进行排序 例如 gt gt gt def get value k print heavy computation for k return a 100 b 30 c 50 d 0 k
  • 手动将 JComponent 放置在 JPanel 内

    我想以编程方式将 JLabel 移动到 JPanel 内的特定位置 我努力了setLocation int x int y 但它不起作用 我试图不使用任何布局管理器 这是一个关于如何在不使用布局管理器的情况下布局组件的精彩教程 http j
  • UITextView 中的文本垂直居中

    我想将文本居中垂直里面一个大UITextView填满整个屏幕 因此 当文本很少时 说几个单词 它会按高度居中 这不是一个关于文本居中 可以在IB中找到的属性 的问题 而是关于放置文本的问题垂直就在中间UITextView if文字很短 所以
  • 以编程方式将 svg 转换为图像

    我正在尝试将 svg 转换为图像 我一直在研究几种工具 但仍然无法实现这一点 1 SVG渲染引擎但我遇到了麻烦 因为它没有文档 这是我的代码 using FileStream fileStream File OpenRead C sampl
  • 使用 Python 删除或删除 CSV 文件中的最后一列

    我有一个包含 5 列的 CSV 文件 使用Python 如何删除最后一列 示例中的header5 我是否缺少一种简单的方法 或者我是否必须循环遍历 CSV 中的所有行并从最后一列中删除每个值 这仍然可能会给我留下不需要的前置逗号 我在 CS
  • 使用 SQLAlchemy 和多处理挂入 Python 脚本

    考虑以下 Python 脚本 它使用 SQLAlchemy 和 Python 多处理模块 这是 Debian squeeze 上的 Python 2 6 6 8 b1 默认 和 SQLAlchemy 0 6 3 3 默认 这是一些实际代码的