Ubuntu18.04上踩坑之pycocoevalcap——meteor.py


这一切源于:

第一次配置双系统时,给Ubuntu分配了太少的空间,导致后来只存放几个Project(还要保存训练文件)就内存不够了,于是下定决心重装Ubuntu!


问题描述:

顺利安装完Ubuntu、pycharm、anaconda、pytorch之后,在旧Ubuntu上可以完美运行的Project在这里爆出了一个bug:

  

    File "/home/teemo/Desktop/code/ggnn/SA-LSTM-master/pycocoevalcap/meteor/meteor.py", line 24, in __init__
         stderr=subprocess.PIPE) 
    File "/home/teemo/anaconda3/envs/SALSTM/lib/python2.7/subprocess.py", line 711, in __init__   
          errread, errwrite)
    File "/home/teemo/anaconda3/envs/SALSTM/lib/python2.7/subprocess.py", line 1343, in _execute_child
          raise child_exception
OSError: [Errno 2] No such file or directory 


尝试解决:

首先想到有可能是python的包的问题,于是我检查了版本包括重新下载包,没有用,所以版本问题排除。我开始去网上查阅了有关的解决方法,唯一有效果(未完全解决)的尝试如下:

在调用Popen的代码段里添加shell=True

self.meteor_cmd = ['java', '-jar', '-Xmx2G', METEOR_JAR, \
                '-', '-', '-stdio', '-l', 'en', '-norm']
        self.meteor_p = subprocess.Popen(self.meteor_cmd, \
                cwd=os.path.dirname(os.path.abspath(__file__)), \
                stdin=subprocess.PIPE, \
                stdout=subprocess.PIPE, \
                stderr=subprocess.PIPE,  \
                shell=Ture)
        # Used to guarantee thread safety
        self.lock = threading.Lock()

之后重新运行却又重新报了错误:

IOError: [Errno 32] Broken pipe

于是我又双叒叕寻找解决方案,看到一篇帖子说可能是java的原因,于是我进入\pycocoevalcap\meteor 路径,执行 java 命令:

java -jar -Xmx2G meteor-1.5.jar - - -stdio -l en -norm

提示找不到java

在输入apt install default-jre安装java后,再次运行命令就不会报错了。

java -jar -Xmx2G meteor-1.5.jar - - -stdio -l en -norm

代码也能完美运行了。

其实此前在Popen代码段里添加shell=True,删除了也不会影响代码运行。

参数详解:
shell: 如果shell为True,那么指定的命令将通过shell执行。如果我们需要访问某些shell的特性,如管道、文件名通配符、环境变量扩展功能,这将是非常有用的。

shell=True参数会让subprocess.call接受字符串类型的变量作为命令,并调用shell去执行这个字符串,当shell=False是,subprocess.call只接受数组变量作为命令,并将数组的第一个元素作为命令,剩下的全部作为该命令的参数。

举个例子来说明:
from subprocess import call    
cmd = "cat test.txt; rm test.txt"    
call(cmd, shell=True)  


上述脚本中,shell=True的设置,最终效果是执行了两个命令
cat test.txt 和 rm test.txt


把shell=True 改为False,
from subprocess import call 
cmd = "cat test.txt; rm test.txt"    
cmd = shlex(cmd)    
call(cmd, shell=False)  

则调用call的时候,只会执行cat的命令,且把 "test.txt;" "rm" "test.txt" 三个字符串当作cat的参数,所以并不是我们直观看到的好像有两个shell命令了。

也许你会说,shell=True 不是很好吗,执行两个命令就是我期望的呀。但其实,这种做法是不安全的,因为多个命令用分号隔开,万一检查不够仔细,执行了危险的命令比如 rm -rf / 这种那后果会非常严重,而使用shell=False就可以避免这种风险。

总体来说,看实际需要而定,官方的推荐是尽量不要设置shell=True。

来源:https://www.cnblogs.com/domestique/p/8056269.html


  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值