Asyncio 函数在从脚本调用时有效,但在 Flask 路由中无效

2024-07-04

我是 Python 和这些库/模块的新手。我正在编写一个简单的 ping 测试网络扫描仪作为学习项目。

我首先使用 asyncio 开发了一个脚本来 ping 网络上的地址

#ip_test.py
import asyncio
import ipaddress

async def ping(addr):
    proc = await asyncio.create_subprocess_exec(
        'ping','-W','1','-c','3',addr,
        stdout=asyncio.subprocess.PIPE
    )
    await proc.wait()
    return proc.returncode

async def pingMain(net):
    #hosts() returns list of Ipv4Address objects
    result = await asyncio.gather(*(ping(str(addr)) for addr in net.hosts()))
    return result

def getHosts(net_): #net_ is an Ipv4Network object
    return asyncio.run(pingMain(net_))
    #Returns list of response codes which I then zip with the list of searched ips

当我打开 python 并运行以下命令时,它按预期工作:

import ip_test as iptest
import ipaddress
print(iptest.getHosts(ipaddress.ip_network('192.168.1.0/29')))
#prints: [0, 0, 0, 1, 1, 1] as expected on this network

然而,最终目标是通过表单输入获取用户的输入(结果记录到数据库中,这是出于说明目的的简化示例)。我通过烧瓶路线收集输入:

@app.route("/newscan",methods=['POST'])
def newScan():
    form = request.form
    networkstring = form.get('network') + "/" + form.get('mask')
    result = iptest.getHosts(ipaddress.ip_network(networkstring))
    return result

当我以这种方式调用模块时,出现错误:Runtime Error: Cannot add child handler, the child watcher does not have a loop attached.

为什么当我导入模块并从命令行运行该函数时它可以工作,但当我使用 Flask 路由中的相同输入调用它时却不起作用?

编辑:回溯:

Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 2463, in __call__
  return self.wsgi_app(environ, start_response)
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 2449, in wsgi_app
  response = self.handle_exception(e)
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1866, in handle_exception
  reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
  raise value
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 2446, in wsgi_app
  response = self.full_dispatch_request()
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1951, in full_dispatch_request
  rv = self.handle_user_exception(e)
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1820, in handle_user_exception
  reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
  raise value
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1949, in full_dispatch_request
  rv = self.dispatch_request()
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1935, in dispatch_request
  return self.view_functions[rule.endpoint](**req.view_args)
File "/app/app.py", line 41, in newScan
  result = iptest.getHosts(ipaddress.ip_network(networkstring))
File "/app/ip_test.py", line 22, in getHosts
  res = asyncio.run(pingMain(net_))
File "/usr/local/lib/python3.7/asyncio/runners.py", line 43, in run
  return loop.run_until_complete(main)
File "/usr/local/lib/python3.7/asyncio/base_events.py", line 579, in run_until_complete
  return future.result()
File "/app/ip_test.py", line 15, in pingMain
  result = await asyncio.gather(*(ping(str(addr)) for addr in net.hosts()))
File "/app/ip_test.py", line 7, in ping
  stdout=asyncio.subprocess.PIPE
File "/usr/local/lib/python3.7/asyncio/subprocess.py", line 217, in create_subprocess_exec
  stderr=stderr, **kwds)
File "/usr/local/lib/python3.7/asyncio/base_events.py", line 1529, in subprocess_exec
  bufsize, **kwargs)
File "/usr/local/lib/python3.7/asyncio/unix_events.py", line 193, in _make_subprocess_transport
  self._child_watcher_callback, transp)
File "/usr/local/lib/python3.7/asyncio/unix_events.py", line 930, in add_child_handler
  "Cannot add child handler, "
RuntimeError: Cannot add child handler, the child watcher does not have a loop attached

您正在尝试从主线程以外的线程运行异步子进程。这需要从主线程进行一些初始设置,请参阅子进程和线程 section https://docs.python.org/3/library/asyncio-subprocess.html#subprocess-and-threads of the asyncio 子流程文档:

标准异步事件循环支持从不同线程运行子进程,但有一些限制:

  • 事件循环必须在主线程中运行。
  • 在从其他线程执行子进程之前,必须在主线程中实例化子观察程序。致电get_child_watcher()主线程中的函数来实例化子观察者。

这里发生的情况是,您的 WSGI 服务器正在使用多个线程来处理传入请求,因此请求处理程序没有在main线。但你的代码使用asyncio.run()开始一个新的事件循环,所以你的asyncio.create_subprocess_exec()调用将失败,因为主线程上没有子观察程序。

您必须从主线程启动一个循环(而不是停止它),然后调用asyncio.get_child_watcher() https://docs.python.org/3/library/asyncio-policy.html#asyncio.get_child_watcher在该线程上,为了让您的代码不会失败:

# to be run on the main thread, set up a subprocess child watcher
assert threading.current_thread() is threading.main_thread()
asyncio.get_event_loop()
asyncio.get_child_watcher()

注意:此限制仅适用于 Python 3.7 之前的版本,该限制已在 Python 3.8 中取消 https://bugs.python.org/issue35621.

然而,只是为了运行一堆子进程并等待它们完成,使用asyncio是矫枉过正;你的操作系统可以并行运行子进程。只需使用subprocess.Popen() https://docs.python.org/3/library/subprocess.html#subprocess.Popen并通过检查每个过程Popen.poll() method https://docs.python.org/3/library/subprocess.html#subprocess.Popen.poll:

import subprocess

def ping_proc(addr):
    return subprocess.Popen(
        ['ping', '-W', '1', '-c', '3', addr],
        stdout=subprocess.DEVNULL,
        stderr=subprocess.DEVNULL
    )

def get_hosts(net):
    # hosts() returns list of Ipv4Address objects
    procs = [ping_proc(str(addr)) for addr in net.hosts()]
    while any(p.poll() is None for p in procs):
        time.sleep(0.1)
    return [p.returncode for p in procs]

Popen.poll()不阻塞;如果Popen.returncode尚未设置,它会检查操作系统的进程状态waitpid([pid], WNOHANG) https://linux.die.net/man/3/waitpid并返回None如果该进程仍在运行,或者现在可用returncode价值。上面只是在循环中检查这些状态,并在其间进行短暂的睡眠以避免抖动。

The asyncio子进程包装器(至少在 POSIX 上)要么使用SIGCHLD通知子进程退出的信号处理程序或(在 Python 3.8 中)每个子进程使用单独的线程来使用阻塞waitpid()调用创建的每个子流程。您可以实现相同的信号处理程序,但要考虑到信号处理程序只能在主线程上注册,因此您必须跳过几个环节才能与传入的信号进行通信SIGCHLD向正确的线程发出信号信息。

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

Asyncio 函数在从脚本调用时有效,但在 Flask 路由中无效 的相关文章

  • 导入文本文件:没有要从文件中解析的列

    我正在尝试从 sys stdin 获取输入 这是hadoop 的map reducer 程序 输入文件为txt格式 数据集预览 196 242 3 881250949 186 302 3 891717742 22 377 1 8788871
  • 配置 argparse 以接受带引号的参数

    我正在编写一个程序 除其他外 它允许用户通过参数指定要加载的模块 然后用于执行操作 我试图建立一种方法来轻松地将参数传递到这个内部模块 并且我试图使用 ArgParse 的action append 让它构建一个参数列表 然后我将通过它 这
  • Flask:如何从模板目录下提供静态文件?

    我使用 Flask 并想要更改我的资产文件夹目录 这是我的文件夹结构 python static js img font css templates default css js img venv app py 我想移动静态文件夹下的所有文
  • 使用 bs4 进行 HTML 解析

    我正在解析一个 HTMl 页面 并且很难弄清楚如何在没有类或 id 的情况下提取某个 p 标签 我试图用经纬度到达 p 标签 这是我当前的代码 import bs4 from urllib import urlopen as uReq th
  • networkx - 根据列表或字典值更改节点大小

    我正在尝试在networkx中制作一个图表 我在为节点分配不同的节点大小时遇到 问题 这是我一直在玩的代码 import sys from collections import defaultdict import networkx as
  • python 中的神经网络:决策/分类总是给出 0.5

    首先我想说我是一个Python初学者 对神经网络也是完全陌生的 当我读到它时 我非常兴奋 并认为我从头开始设置了一些代码 参见下面的代码 但不知怎的 我的代码无法正常工作 我猜想存在一些重大错误 在算法和编程中 但我现在找不到他们 所以 在
  • 如何使用Python读取MP3中的ID3标签? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 有人有在 MP3 文件或 WMA 文件中读写 ID3 标签的经验吗 有一些库 但我想从头开始 深入Python https web a
  • Pandas:处理测试中看不见的数据

    我有一个训练数据集 正在构建一些机器学习模型 我无权访问测试集 并且想要处理在训练中未观察到测试中的分类特征之一的可能性 这是一个玩具示例 说明了我的意思 我有一个数据框 old 像这样 old pd DataFrame car Audi
  • Python将html ascii编码文本转换为utf8

    我有一个 xml 文件 需要将其转换为 utf8 不幸的是 这些实体包含这样的文本 047 mytext 044 我正在使用编解码器库将文件转换为 utf8 但 html 实体无法使用它 有没有一种简单的方法可以摆脱html编码 Thank
  • 嵌入式Python,导入数学错误

    首先我使用的是 Mac OSX 10 12 6 我想在我的 C 应用程序中嵌入 python 环境 我把 github python 项目放在https github com python cpython https github com
  • Python:多 QQ 绘图

    我是新人 通常来自 R 我想创建一个包含多行的 QQ Plot 我有一个测试版分布式数据集 我想尝试不同的 beta 分布参数并在oneQQ Plot 以便更好地进行比较 如果我尝试下面的代码 每个图都有相同的颜色 并且我得到 3 条 QQ
  • 如何对不同类型的列表进行排序?

    我需要使用 python 3 对列表进行排序 可能有strings integers floats or tuples etc 我目前正在尝试正确使用sort函数使用key参数如下 data sort key gen key def gen
  • Lightgbm OSError,库未加载

    如果我简单地这样做 import lightgbm as lgb 我越来越 python script py Traceback most recent call last File script py line 4 in
  • ValueError:在 ECB 模式下数据必须与块边界对齐

    我正在使用以下代码在 ECB 模式下尝试 aes 128 加密 from Crypto Cipher import AES key abcdefghijklmnop cipher AES new key encode utf8 AES MO
  • pyqt 中的代码编辑器示例

    我尝试学习一些Qt PyQt 为此 我使用了代码编辑器示例 http doc qt io qt 4 8 qt widgets codeeditor example html的文档 当前行的突出显示效果很好 但行号不显示 实际上LineNum
  • Python 解释器优化

    假设我有一个字符串x Python 解释器是否足够聪明 能够知道 string replace x x 应转换为NOP 我怎样才能找到这个 是否有任何参考资料显示解释器能够根据句法分析动态执行哪种类型的优化 不 Python 不能对 NOP
  • Python:汇总和聚合 DataFrame 中的组和子组

    我正在尝试构建一个表 其中的组按子组划分 并包含每个子组的计数和平均值 例如 我想转换以下数据框 到一个看起来像这样的表 其中interval是一个更大的组和列a thru i成为组内的子组 每个单元格中具有相应子组的计数和平均值 我尝试过
  • 来自 Abaqus/CAE 的 Python 多处理

    I am using a commercial application called Abaqus CAE1 with a built in Python 2 6 interpreter and API I ve developed a l
  • 在Python中返回外部函数错误

    这就是问题 给定以下 Python 程序 假设用户从键盘输入数字 4 返回的值是多少 N int input enter a positive integer counter 1 while N gt 0 counter counter N
  • 使用 M1 Mac 进行 Python 多处理

    我有一台 Mac Mac Os 11 1 Python Ver 3 8 2 需要在多处理中工作 但程序不起作用 import multiprocessing def func index int print index manager mu

随机推荐

  • 如何使用 Google App Script 在 Google Drive 中创建大文件?

    我正在尝试使用 Google Apps 脚本在 Google Drive 中创建一个大文件 该文件合并了三个文件 我的代码是 function unirFicheros idDirectorio nombreFichero numeroFi
  • django value_list 外键中所有字段

    我有一个类 它有另一个类的外键 class MyEvent models Model msg models ForeignKey MyMessage event type models IntegerField choices EVENTS
  • QTreeView、QFileSystemModel、setRootPath 和 QSortFilterProxyModel 以及用于过滤的 RegExp

    我需要显示特定目录的 QTreeView 并且我想让用户能够使用 RegExp 过滤文件 据我了解 Qt 文档 我可以使用标题中提到的类来实现这一点 如下所示 Create the Models QFileSystemModel fileS
  • 通过key查询模型

    我想做的是查询数据存储中的模型 其中密钥是not我已经拥有的对象的密钥 这是一些代码 class User db Model partner db SelfReferenceProperty def text message self ms
  • ASM 16Bit 将输入缓冲区字符串转换为数字

    也许有人可以帮助我 我正在尝试打印 用户输入的数量 所以我需要将字符串转换为数字 我正在尝试循环执行此操作 但遇到一些问题 我的代码无法正常工作 它正在打印 65535 基本上这是最大值 也许有人可以解释我的问题出在哪里 MODEL sma
  • 将矩阵的每一列乘以另一个矩阵

    我有一个M x N矩阵 我想将每个相乘N列由aM x M矩阵 以下在循环中执行此操作 但我不知道如何对其进行矢量化 u repmat sin 2 pi f t n 1 W rand n answer size u for i 1 size
  • 连接到 Redis 与多个工作线程一起使用时遇到问题

    我在使用 Heroku 中的 kue 连接到 redis 来处理多个工作进程时遇到问题 我可以在本地主机上与多个工作人员连接到 redis 但在与 redis to go 连接时似乎会中断 只有当我运行多个 kue 工作线程 进程时 这似乎
  • 对 .NET Remoting CAO 的暴力攻击

    我正在尝试使用 NET 远程客户端激活对象来在多次调用期间保留客户端的身份验证信息 而不是实现需要客户端在每次调用中发送会话 ID 的会话管理系统 正如 MSDN 所说 当客户端使用 new 运算符提交对服务器对象的请求时 激活请求消息将发
  • 如何使用 MVVM light 处理 WP 8.1 上的后退按钮?

    我正在寻找适当的方法来处理 Windows Phone 8 1 WinRT 上的后退按钮按下事件NavigationService在 MVVM light 5 上可用 到目前为止 我认为最好的地方是在ViewModelLocator通过注册
  • R: tibble::lst 名称中不需要的引号

    我最近才了解到tibble lst 它创建一个列表对象 但自动命名列表项 我用它作为快捷方式 gt 使用名称作为工作流程 id论证中map dfr 所以自动命名确实很有帮助 然而 这些名称都带有引号 我注意到这一点是因为它们笨拙地打印在轴刻
  • Python将html ascii编码文本转换为utf8

    我有一个 xml 文件 需要将其转换为 utf8 不幸的是 这些实体包含这样的文本 047 mytext 044 我正在使用编解码器库将文件转换为 utf8 但 html 实体无法使用它 有没有一种简单的方法可以摆脱html编码 Thank
  • 如何让电报机器人通过链接加入频道?

    我想编写一个爬虫机器人 它可以浏览频道并找到具有高观看次数的消息 是否可以通过链接将机器人添加到频道 机器人是否可以读取频道中广播的消息 机器人是否可以读取频道中消息的查看计数值 如果上述任何一个问题是可能的 那么解决方案是什么 只有创建者
  • JSON e 和 JSON E

    在 JSON 网站上here http www json org 它解释了 JSON 对象 的不同可能性 然而 在数字部分 这些出现 e e e E E E 1 这些代表什么 在寻找答案的过程中
  • 正则表达式在日期中添加连字符

    在 R 中 我有一个如下所示的字符串 x lt c 20130603 00 00 03 102 20130703 00 01 03 103 20130804 00 03 03 104 我想通过使用一个单一的看起来像下面gsub命令 而不是使
  • 当object.next到达末尾时如何指向第一个元素?

    从数组创建枚举对象a 有没有什么方法可以指向 first when next到达终点 a 5 1 b a to enum b next gt 5 b next gt 1 b next gt Stop Iteration Iteration
  • mySQL 和 XAMPP 端口冲突

    我已经使用 XAMPP Apache 一段时间了 最 近决定安装 MySQL 然而 它们似乎是矛盾的 MySQL 似乎优先 并且它运行正常 但是 XAMPP Apache 在尝试启动 Apache 时给我此错误消息 03 07 32 AM
  • 在 Windows Server 2003 上安装 PHP 5 - %1 不是有效的 Win32 应用程序

    我正在尝试在带有 IIS 6 的 Windows Server 2003 环境上安装 PHP 5 安装 PHP 并在 IIS 中进行必要的更改后 出现以下错误 1 is not a valid Win32 application 服务器不是
  • 无法使用react-native-xmpp连接openfire

    我有一个反应本机聊天应用程序 我使用 USB 调试在我的 Android 手机上运行 并且我使用 OPENFIRE 作为聊天服务器 为了与 Openfire 连接 我正在使用库 反应本机xmpp 下面是使用react native xmpp
  • 嵌入式Python,导入数学错误

    首先我使用的是 Mac OSX 10 12 6 我想在我的 C 应用程序中嵌入 python 环境 我把 github python 项目放在https github com python cpython https github com
  • Asyncio 函数在从脚本调用时有效,但在 Flask 路由中无效

    我是 Python 和这些库 模块的新手 我正在编写一个简单的 ping 测试网络扫描仪作为学习项目 我首先使用 asyncio 开发了一个脚本来 ping 网络上的地址 ip test py import asyncio import i