为什么 subprocess.Popen 不等到子进程终止?

2023-11-25

我对 Python 的 subprocess.Popen 方法有疑问。

这是一个演示该问题的测试脚本。它正在 Linux 机器上运行。

#!/usr/bin/env python
import subprocess
import time

def run(cmd):
  p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
  return p

### START MAIN
# copy some rows from a source table to a destination table
# note that the destination table is empty when this script is run
cmd = 'mysql -u ve --skip-column-names --batch --execute="insert into destination (select * from source limit 100000)" test'
run(cmd)

# check to see how many rows exist in the destination table
cmd = 'mysql -u ve --skip-column-names --batch --execute="select count(*) from destination" test'
process = run(cmd)
count = (int(process.communicate()[0][:-1]))

# if subprocess.Popen() waited for the child to terminate than count should be
# greater than 0
if count > 0:
  print "success: " + str(count)
else:
  print "failure: " + str(count)
  time.sleep(5)

  # find out how many rows exists in the destination table after sleeping
  process = run(cmd)
  count = (int(process.communicate()[0][:-1]))
  print "after sleeping the count is " + str(count)

通常该脚本的输出是:

success: 100000

但有时是

failure: 0
after sleeping the count is 100000

请注意,在失败的情况下,插入后立即选择显示 0 行,但在休眠 5 秒后,第二个选择正确显示行数 100000。我的结论是以下其中一项是正确的:

  1. subprocess.Popen 不等待子线程终止 - 这似乎与文档相矛盾
  2. mysql插入不是原子的-我对mysql的理解似乎表明插入是原子的
  3. select 没有立即看到正确的行数 - 据一位比我更了解 mysql 的朋友说,这也不应该发生

我缺少什么?

仅供参考,我知道这是一种从 Python 与 mysql 交互的 hacky 方式,而 MySQLdb 可能不会有这个问题,但我很好奇为什么这种方法不起作用。


subprocess.Popen,实例化后运行该程序。然而,它不会等待它——它会在后台触发它,就像你输入了一样cmd &在一个壳里。因此,在上面的代码中,您基本上定义了一个竞争条件 - 如果插入可以及时完成,它将显示正常,但如果不能,您会得到意外的输出。你没有等待你的第一次run()'d PID 完成后,您只需返回它的Popen实例并继续。

我不确定这种行为与文档有何矛盾,因为 Popen 上有一些非常明确的方法似乎表明不等待它,例如:

Popen.wait()
  Wait for child process to terminate. Set and return returncode attribute.

不过,我确实同意该模块的文档可以改进。

要等待程序完成,我建议使用subprocess的便捷方法,subprocess.call,或使用communicate on a Popen对象(用于需要标准输出的情况)。您已经在第二次通话中执行此操作了。

### START MAIN
# copy some rows from a source table to a destination table
# note that the destination table is empty when this script is run
cmd = 'mysql -u ve --skip-column-names --batch --execute="insert into destination (select * from source limit 100000)" test'
subprocess.call(cmd)

# check to see how many rows exist in the destination table
cmd = 'mysql -u ve --skip-column-names --batch --execute="select count(*) from destination" test'
process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
try: count = (int(process.communicate()[0][:-1]))
except: count = 0

此外,在大多数情况下,您不需要在 shell 中运行该命令。这是其中一种情况,但您必须像序列一样重写命令。这样做还可以让您避免传统的 shell 注入,并且不用担心引用,如下所示:

prog = ["mysql", "-u", "ve", "--execute", 'insert into foo values ("snargle", 2)']
subprocess.call(prog)

这甚至可以工作,并且不会像您期望的那样注入:

prog = ["printf", "%s", "<", "/etc/passwd"]
subprocess.call(prog)

以交互方式尝试一下。您可以避免 shell 注入的可能性,特别是在您接受用户输入时。我怀疑您正在使用不太令人敬畏的字符串方法与子进程通信,因为您在使序列正常工作时遇到了麻烦:^)

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

为什么 subprocess.Popen 不等到子进程终止? 的相关文章

  • Apache 子进程已退出,状态为 255

    经过大量的搜索 尝试 修复 等待和哭泣 在我放弃之前 我想为这个错误抓住最后的机会 我们正在奔跑Microsoft Windows Server 2012 Apache 2 4 6 Win64 OpenSSL 1 0 1e PHP 5 5
  • Mypy 无法从文字列表推断项目的类型

    我有一个变量x和一个文字列表 例如 0 1 2 我想转换x这些文字之一 如果x在列表中 我将其退回 否则我返回一个后备值 from typing import Literal Set Foo Literal 0 1 2 foos Set F
  • Series.sort() 和 Series.order() 有什么区别?

    s pd Series nr randint 0 10 5 index nr randint 0 10 5 s Output 1 3 7 6 2 0 9 7 1 6 order 按值排序并返回一个新系列 s order Output 2 0
  • MySQL 两种日期格式之间的转换

    用户将以这种格式输入日期 2017 年 2 月 17 日 存储在 mysql 数据库中的日期格式如下 2015 02 17 00 00 00 我想做的是 SELECT FROM insurance where DATE FORMAT in
  • 在Python上获取字典的前x个元素

    我是Python的新手 所以我尝试用Python获取字典的前50个元素 我有一本字典 它按值降序排列 k 0 l 0 for k in len dict d l 1 if l lt 51 print dict 举个小例子 dict d m
  • Arcpy 模数在 Pycharm 中不显示

    如何将 Arcpy 集成到 Pycharm 中 我尝试通过导入模块但它没有显示 我确实知道该模块仅适用于 2 x python arcpy 在 PyPi Python 包索引 上不可用 因此无法通过 pip 安装 要使用 arcpy 您需要
  • python 中的 <> 运算符有什么作用?

    我刚刚遇到这个here http www feedparser org feedparser py 总是这样使用 if string1 find string2 lt gt 1 pass 什么是 lt gt 运算符这样做 为什么不使用通常的
  • Python Anaconda:如何测试更新的库是否与我现有的代码兼容?

    我在 Windows 7 机器上使用 Python 2 7 Anaconda 安装进行数据分析和科学计算 当新的库发布时 例如新版本的 pandas patsy 等 您建议我如何测试新版本与现有代码的兼容性 是否可以在同一台机器上安装两个
  • Spark 和 Python 使用自定义文件格式/生成器作为 RDD 的输入

    我想问一下 Spark 中输入的可能性 我可以看到从http spark apache org docs latest programming guide html http spark apache org docs latest pro
  • 给定一个排序数组,就地删除重复项,使每个元素仅出现一次并返回新长度

    完整的问题 我开始在线学习 python 但对这个标记为简单的问题有疑问 给定一个排序数组 就地删除重复项 使得每个 元素只出现一次并返回新的长度 不分配 另一个数组的额外空间 您必须通过修改输入来完成此操作 数组就地 具有 O 1 额外内
  • 如何查找或安装适用于 Python 的主题 tkinter ttk

    过去 3 个月我一直在制作一个机器人 仅用代码就可以完美运行 现在我的下一个目标是为它制作一个 GUI 但是我发现了一些障碍 主要的一个是能够看起来不像一个 30 年前的程序 我使用的是 Windows 7 我仅使用 Python 3 3
  • 使用 Python 将连续日期分组在一起

    Given dates datetime 2014 10 11 datetime 2014 10 1 datetime 2014 10 2 datetime 2014 10 3 datetime 2014 10 5 datetime 201
  • 检测是否从psycopg2游标获取?

    假设我执行以下命令 insert into hello username values me 我跑起来就像 cursor fetchall 我收到以下错误 psycopg2 ProgrammingError no results to fe
  • minizinc python 安装

    我通过 anaconda 提示符在 python 上安装了 minizinc 就像其他软件包一样 pip install minizinc 该软件包表示已成功安装 我可以导入该模块 但是 我正在遵循基本示例https minizinc py
  • rpy2 无法加载外部库

    希望有人能帮忙解决这个问题 R版本 2 14 1rpy2版本 2 2 5蟒蛇版本 2 7 3 一直在尝试在 python 脚本中使用 rpy2 加载 R venneuler 包 该包以 rJava 作为依赖项 venneuler 和 rJa
  • 如何从namedtuple实例列表创建pandas DataFrame(带有索引或多索引)?

    简单的例子 from collections import namedtuple import pandas Price namedtuple Price ticker date price a Price GE 2010 01 01 30
  • pandas 中数据帧中的随机/洗牌行

    我目前正在尝试找到一种方法来按行随机化数据框中的项目 我在 pandas 中按列洗牌 排列找到了这个线程 在 pandas 中对 DataFrame 进行改组 排列 https stackoverflow com questions 157
  • 将 Keras 集成到 SKLearn 管道?

    我有一个 sklearn 管道 对异构数据类型 布尔 分类 数字 文本 执行特征工程 并想尝试使用神经网络作为我的学习算法来拟合模型 我遇到了输入数据形状的一些问题 我想知道我想做的事情是否可能 或者我是否应该尝试不同的方法 我尝试了几种不
  • 如何使用 python 定位和读取 Data Matrix 代码

    我正在尝试读取微管底部的数据矩阵条形码 我试过libdmtx http libdmtx sourceforge net 它有 python 绑定 当矩阵的点是方形时工作得相当好 但当矩阵的点是圆形时工作得更糟 如下所示 另一个复杂问题是在某
  • IndexError - 具有匀称形状的笛卡尔 PolygonPatch

    我曾经使用 shapely 制作一个圆圈并将其绘制在之前填充的图上 这曾经工作得很好 最近 我收到索引错误 我将代码分解为最简单的操作 但它甚至无法执行最简单的循环 import descartes import shapely geome

随机推荐