I am sure you are done wanting to think about this, and I am sorry I didn’t see this sooner, but as I do not have easy access to a windows machine I didn’t want to give untested advice. But I think the discussion could hold general interest for anyone radiance scripting with python. It is also an opportunity for a shameless plug, and call for help. But first…
Your problems stemmed from using the the “>” redirect in the command, the “correct” way is to let python manage the file handling. Your ultimate solution:
subprocess.run(cmd.split(' '), shell=True, capture_output=True)subprocess.run(cmd.split(' '), shell=True, capture_output=True)
worked because of the 'shell=True parameter. While I don’t have Windows, passing shell=True to os.system likely works as well:
os.system(f"rtpict -vf {view_name} {res_string} {img_opts} tmp.oct > tmp.hdr", shell=True)
Now, you probably came across all sorts of advice on the internet about how this is VERY BAD! and causes all sorts of exploitable security issues in your code, but for a simple script there is nothing wrong with doing it this way, and in any case, your subprocess.run command exposes shell access in the same way.
For blocking commands, the correct subprocess command (to avoid the communicate() confusion) is subprocess .call():
from subprocess import call
import shlex #does shell style lexical analysis
cmd = shlex.split(f"rtpict -vf {view_name} {res_string} {img_opts} tmp.oct")
f = open("tmp.hdr", "wb")
call(cmd, stdout=f)
f.close()
You are right that things get more complicated when you want to handle piping, this is where Popen becomes necessary. Say I wanted to run your command the old fashioned vwrays | rrtrace way:
from subprocess import Popen, PIPE
import shlex
vwrays = shlex.split(f"vwrays -ff -vf {view_name} {res_string}")
rtrace = shlex.split(f"rtrace {res_string} -ld- -ffc {img_opts} tmp.oct")
out = open("tmp.hdr", "wb")
f = Popen(vwrays, stdout=PIPE)
Popen(rtrace, stdin=f.stdout, stdout=out).communicate()
out.close()
This is all certainly way more complicated than a simple script should be, but these commands help navigate the cross platform differences to help avoid ugh… Windows headaches and such. Fortunately, others (like me) have spent a bunch of time coding the same type of thing over and over again, soo, now time for a shameless plug: I wrote a python library specifically for dealing with the types of tasks that radiance scripters encounter. The bulk of the library is to help write consistent and intuitive command line programs with powerful argument parsing using optional configuration files, but the work-horse method is pipeline():
from clasp import script_tools
vwrays = f"vwrays -ff -vf {view_name} {res_string}"
rtrace = f"rtrace {res_string} -ld- -ffc {img_opts} tmp.oct"
pcomb = "pcomb -e 'lo=if(li(1),1,0)' -"
cmds = [vwrays, rtrace, pcomb]
script_tools.pipeline(commands, outfile="tmp2.hdr", writemode="wb", close=True)
Isn’t it beautiful? I am not sure what you are doing with tmp2.hdr, but you can easily extend the pipe and get rid of all the intermediate files. You can even delegate the octree creation with some special syntax:
rtrace = f"rtrace {res_string} -ld- -ffc {img_opts} $(oconv {scene_files})"
And you may ask yourself: So how do get this wonderful tool?
pip install clasp
And you may ask yourself: where do you learn how to use it? right here
And you may ask yourself: Well, I heard your shameless plug, and this all seems wonderful, but I also recall you needed help?
Yeah, so now I must confess: clasp has not been tested on Windows and I do not expect it to work out of the box. But it is fully open source project and I would love a collaborator to help build up the test suite and debug on windows. If that is you, please get in touch.
Apologies for hijacking a windows thread to promote a tool untested on windows, and a big apology to David Byrne.