Reputation: 372
I have the following snippet which I use with every code I run.
import sys
sys.stdin, sys.stdout = open('input', 'r'), open('output', 'w')
Is there any way I can make these two lines run with every .py
I run.
Also on Sublime Text this is the build configuration I used to redirect the output to a file, but it is not working.
{
"cmd": ["/home/jithin/venv/bin/python", "-u", "$file" ,">","/home/jithin/temp/hackerrank/output"],
"file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
"selector": "source.python"
}
Is there any flags like --stdout to redirect the output of the code to a file.
NB. I cannot use include any lines in the code because I am practising competitive programming, so I usually copy and paste the code from the question to ST. If there was a differemt method I wouldn't need to include the above snippet everytime. Also for pasting back I could simply use Ctrl + A and Ctrl + V.
Upvotes: 2
Views: 208
Reputation: 22791
As far as I can see, Python has no built in way to allow you to execute arbitrary script commands along with a full on script, so the options available boil down to either manually putting the boilerplate in every file or dynamically adding it there when you run the code.
Generally speaking, my recommendation would be create a snippet that inserts this code for you so that you don't have to manually copy and paste it. To do that, you can choose Tools > Developer > New Snippet...
and replace the stub with the following, then save the file as a sublime-snippet
file in the location Sublime suggests:
<snippet>
<content><![CDATA[
import sys
sys.stdin, sys.stdout = open('input', 'r'), open('output', 'w')
]]></content>
<tabTrigger>stub</tabTrigger>
<description>Insert IO redirect stubs for competetive coding</description>
<scope>source.python</scope>
</snippet>
Change the tab trigger as appropriate, but now in a new Python file stub
Tab will insert the code for you.
It is also possible to construct a build that will automatically add the stub onto the start of every Python file that's executed, if you'd rather do that (but the snippet is much easier).
For that, there is this plugin (see this video on installing plugins if you're not sure how to use one).
import sublime
import sublime_plugin
import os
import tempfile
from Default.exec import ExecCommand
_stub = """
import sys
sys.stdin, sys.stdout = open('input', 'r'), open('output', 'w')
"""
class PythonWithRedirectExecCommand(ExecCommand):
def run(self, **kwargs):
view = self.window.active_view()
if view.file_name() is None or not os.path.exists(view.file_name()):
return self.window.status_message("Cannot build; no file associated with the current view")
self.tmp_file = self.get_temp_file(view)
variables = {"temp_file": self.tmp_file}
kwargs = sublime.expand_variables(kwargs, variables)
super().run(**kwargs)
def get_temp_file(self, view):
handle, name = tempfile.mkstemp(text=True, suffix=".py")
with os.fdopen(handle, mode="wt", encoding="utf-8") as handle:
handle.write(_stub)
with open(view.file_name()) as source:
handle.write(source.read())
return name
# NOTE: If you are using Sublime Text 3, change this line and the
# next use to use finished instead of on_finished.
def on_finished(self, proc):
super().on_finished(proc)
# If the current build didn't finish or it was manually killed, leave.
if proc != self.proc or proc.killed:
return
try:
# If the build succeeded, delete the temporary file; we will
# leave it alone if the build fails so that it's possible to
# navigate to it.
exit_code = proc.exit_code()
if exit_code == 0 or exit_code is None:
os.remove(self.tmp_file)
finally:
self.tmp_file = None
This implements a replacement build target which, when executed, will create a temporary file containing the stub content as well as the contents of the current file.
Important note: This was developed in Sublime Text ~~4~~; it will also work in Sublime Text 3, but you need to change both references to on_finished
to finished
if you're using ST3; otherwise the plugin won't clean up temporary files. Probably also worth noting that for the reasons outlined below, if the run fails the temporary file isn't erased.
To use it, you want a build system similar to this (modify the command as appropriate; this is a generic build):
{
"target": "python_with_redirect_exec",
"cancel": {"kill": true},
"cmd": ["python3", "-u", "\\$temp_file"],
"file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
"selector": "source.python",
"working_dir": "${file_path}",
"env": {"PYTHONIOENCODING": "utf-8"},
"windows": {
"cmd": ["py", "-u", "\\$temp_file"],
},
}
The important notes here are the target
and cancel
, which tie the build to the command provided by the plugin, the working_dir
which makes sure that the current directory is the directory the current file is in (since that is where the input
and output
files are expected to be), and that the \\$temp_file
is used to reference the temporary output file that contains the resulting code.
As a note on this, if an error occurs, the line numbers will be slightly off in the errors because they are referencing the file that has extra content at top, and if you navigate to it you'll open the temporary file, which is not the one you should probably be editing.
So, all things told, the snippet is probably the safest fastest way to go.
Upvotes: 1