第一次配置双系统时,给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