c语言popen函数多线程,关于多线程:多线程环境中的Python-Subprocess-Popen行为不一致...

我在线程内部运行以下代码。." executable"为每个输入" url"产生唯一的字符串输出:

p = Popen(["executable", url], stdout=PIPE, stderr=PIPE, close_fds=True)

output,error = p.communicate()

print output

当上面的代码针对多个输入``URL''执行时,子进程p的``输出''是不一致的。对于某些URL,子进程被终止而不产生任何``输出''。 我尝试为每个失败的'p'实例打印p.returncode(失败的url在多次运行中也不一致),并以'error'值作为空字符串返回'-11'作为返回码。有人可以建议一种方法 在多线程环境中每次运行都能获得一致的行为/输出?

一般而言,我们需要有关您的可执行文件和python程序的更多信息。听起来好像做错了什么。您确定发送的网址正确返回了吗?您可以直接在python中执行可执行文件的操作吗?然后,您可以使用多重处理模块。

@WilliamDenman:hi..executable是一个C程序二进制文件,它在stdout上为给定的输入url生成JSON字符串输出..其余的python代码只是解析该输出字符串..让我知道您是否需要更多信息。

@WilliamDenman我可以肯定C可执行二进制文件可以正常工作,就像在串行执行的情况下一样,每个URL生成的输出是一致的。我无法用python代码替换C可执行文件。

"打印"不是线程安全的...

如何执行多个输入网址。请输入您如何执行此操作的完整代码。您在问题中遇到的方式p.communicate()将阻塞,直到该过程完成为止,因此不会并行执行任何工作。

@dbra:嗨..任何解决该问题的方法在python中?

@WilliamDenman:我是这样做的:urls = [url1,url2,url3] for url in urls: Worker(url) Worker是执行问题中提到的代码的线程..您对p.communicate是正确的..您可能会注意到这里..我并行完成工作因为每个线程执行单个子流程实例,该实例处理分配给该特定线程的单个url。

@SagarG:您可以将输出推送到队列(列表)上,并使用额外的线程进行打印,或者可以使用信号量同步打印,或者可以使用原子AFAIK的sys.stdout.write。

@dbra:问题似乎不是由于打印不是线程安全的。.因为当我将每个线程的输出记录到文件中时..每个输出都正确地写入了(不必担心顺序)输出)..即使对于失败的URL,我也看到异常消息被写入..

您确实需要在问题中包含完整的代码。我觉得@dbra在正确的轨道上。但是,如果没有定义Worker函数,我们实际上只是在猜测一个解决方案。

@WilliamDenman:请看下面"塞巴斯蒂安"提到的代码。它产生-11作为少数子流程的return_code。我现在试图找出是什么原因导致子流程返回-11。是C可执行文件还是python-multithreading。

我现在几乎可以肯定的是,您的C程序正在做一些奇怪的事情。您正在使用哪个版本的Python?尝试使用最新的3.2.x,看看是否得到相同的结果。您是否自己编写了C程序?如果不是,那么您将无法确定它没有执行线程安全的操作。

-11作为返回码可能意味着C程序不合适,例如,您启动了太多子进程,这会导致C可执行文件中出现SIGSERV。您可以使用multiprocessing.ThreadPool,current.futures.ThreadPoolExecutor,基于线程+基于队列的解决方案来限制并发子进程的数量:

#!/usr/bin/env python

from multiprocessing.dummy import Pool # uses threads

from subprocess import Popen, PIPE

def get_url(url):

p = Popen(["executable", url], stdout=PIPE, stderr=PIPE, close_fds=True)

output, error = p.communicate()

return url, output, error, p.returncode

pool = Pool(20) # limit number of concurrent subprocesses

for url, output, error, returncode in pool.imap_unordered(get_url, urls):

print("%s %r %r %d" % (url, output, error, returncode))

确保可执行文件可以并行运行,例如,它不使用某些共享资源。要测试,您可以在shell中运行:

$ executable url1 & executable url2

Could you please explain more about"you are starting too many subprocesses and it causes SIGSERV in the C executable" and possibly solution to avoid that..

可能的问题:

"过程太多"

->"系统或其他资源不足的内存"

->"触发C代码中原本为隐藏或罕见的错误"

->"非法内存访问"

-> SIGSERV

建议的上述解决方案是:

"限制并发进程数"

->"足够的内存或系统中的其他资源"

->"错误是隐藏的还是罕见的"

->没有SIGSERV

了解C ++中的SIGSEGV运行时错误是什么?简而言之,如果程序试图访问它不应该访问的内存,则该程序将被该信号杀死。这是此类程序的示例:

/* try to fail with SIGSERV sometimes */

#include

#include

#include

int main(void) {

char *null_pointer = NULL;

srand((unsigned)time(NULL));

if (rand() < RAND_MAX/2) /* simulate some concurrent condition

e.g., memory pressure */

fprintf(stderr,"%c

", *null_pointer); /* dereference null pointer */

return 0;

}

如果使用上述Python脚本运行它,则它偶尔会返回-11。

Also p.returncode is not sufficient for debugging purpose..Is there any other option to get more DEBUG info to get to the root cause?

我不会完全排除Python方面,但问题很可能是C程序。您可以使用gdb获取回溯,以查看错误来自调用栈的何处。

我正在使用"使用Queue的子进程+线程(手动池)解决方案"方法。pool_size =100。请您解释一下有关"您启动了太多子进程,并在C可执行文件中导致SIGSERV"的问题,并可能提出解决方案 避免那样

我尝试了上面的代码,并确认它为几个子进程返回-11。对于失败的情况,输出和错误将输出空字符串。。print("%s %r %r %d" % (url, output, error, returncode))同样,p.returncode不足以用于调试。是否还有其他选项可以获取更多信息? 调试信息以获得根本原因?

@SagarG:Ive从评论中添加了对您问题的答案。

返回代码-11似乎表明您的C程序不正确。

通常,如果您尝试使用多个线程,则应确切了解所调用程序的实现方式。如果没有,您将遇到类似这样的奇怪而晦涩的错误。

如果您无权访问C可执行文件的源代码,则要么必须用C编写自己的线程安全版本,要么我建议将外部程序实现为Python函数。然后,您可以将其与multiprocessing模块并行化。

Python非常擅长创建和分析JSON,重新实现C程序可能是一个不错的练习。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值