缘起:
我的一个项目一些参数需要可设定,于是做了一个web页面用来填充这些参数,填充完了之后再进行执行该脚本,返回该脚本的输出或是错误,整个工作在web上完成。
问题:
在操作的过程中遇到的问题是,如何给脚本传入数据,原先是写死在脚本中, 从一个指定的文件里读数据进行处理,但是不够灵活,另外脚本执行完了还有一个垃圾数据文件不优雅,于是想到使用stdin可以重定向来导入数据,如果单纯从stdin导入又是简单的,但是我希望做成如果stdin有数据,从stdin导入,如果没有再使用默认的从 文件中导入中,这时候就遇到一个问题non-blocking stdin reading,为了使stdin没有数据时不一直阻塞,使用了select来polling文件描述符是否有数据,在指定时间没有数据就切换到文本方式导入。
由于cStringIO.StringIO不是一个真的文件,它就没有fd了,因此有两种方法,一种是文件,一种是管道,我创建了一个匿名管道,来输入数据。
亮点:
本项目是对http://pythonwebshell.appspot.com/interactive的一个定制版本 ,ihere同学给了指点,代码主要来自gae sdk
以下是主要代码
对管理一直不理解,这次算是一次练习吧
之前使用cStringIO.StringIO,("")来mock file给sys.stdin一般是没有问题的,但是由于要使用select来判断文件描述符是否有输入,就需要一个带文件描述符的真实文件,
要么是文件,要么就是管道,
因为是动态构建,就没必要产生文件了还要删除,下面是部分涉及到的代码
i=int(dict["testNum"])
r="\n".join(dict["list_result"].split("\n")[:i])
fdr,fdw=os.pipe()
os.write(fdw,r)
os.close(fdw)
f=os.fdopen(fdr)
sys.stdin=f
sys.stdout = results_io
try:
compiled_code = compile(dict["list_fetch_code"].encode("utf-8"), g.list_fetch_code_filename, 'exec')
exec(compiled_code,globals())
except Exception, e:
traceback.print_exc(file=results_io)
except Exception,e:
print e,"#############################################"
finally:
sys.stdout = save_stdout
script.py
content=""
if not select.select([sys.stdin,],[],[],0.0)[0]:
print "load from %s"%list_links_file
content=open(list_links_file,"r").read()
else:
print "load from stdin"
content=sys.stdin.read()
urls=content.strip().split("\n")
over