首页 > 解决方案 > 每次在 sublime 文本上运行时运行一个 python 片段

问题描述

我有以下代码片段,我在运行的每个代码中都使用它。

import sys
sys.stdin, sys.stdout = open('input', 'r'), open('output', 'w')

有什么办法可以让这两条线在.py我每次运行时都运行。

同样在 Sublime Text 上,这是我用来将输出重定向到文件的构建配置,但它不起作用。

{
    "cmd": ["/home/jithin/venv/bin/python", "-u", "$file" ,">","/home/jithin/temp/hackerrank/output"],
    "file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
    "selector": "source.python"
}
    

是否有像 --stdout 这样的标志来将代码的输出重定向到文件。

注意。我不能在代码中使用包含任何行,因为我正在练习竞争性编程,所以我通常将代码从问题复制并粘贴到 ST。如果有不同的方法,我不需要每次都包含上面的代码段。同样对于粘贴回来,我可以简单地使用 Ctrl + A 和 Ctrl + V。

标签: pythonsublimetext3

解决方案


据我所见,Python 没有内置方式允许您执行任意脚本命令以及完整的脚本,因此可用的选项归结为手动将样板文件放入每个文件中,或者在您将样板文件动态添加到那里时运行代码。

一般来说,我的建议是创建一个片段,为您插入此代码,这样您就不必手动复制和粘贴它。为此,您可以选择Tools > Developer > New Snippet...存根并将其替换为以下内容,然后将文件另存为sublime-snippetSublime 建议的位置中的文件:

<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>

根据需要更改选项卡触发器,但现在在新的 Python 文件stubTab中将为您插入代码。

如果您愿意,也可以构建一个自动将存根添加到每个执行的 Python 文件的开头的构建(但代码片段更容易)。

为此,有这个插件(如果您不确定如何使用插件,请参阅有关安装插件的视频)。


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

这实现了一个替换构建目标,当它执行时,将创建一个包含存根内容以及当前文件内容的临时文件。

重要提示:这是在 Sublime Text ~~4~~ 中开发的;它也可以在 Sublime Text 3 中使用,但是如果您使用的是 ST3,则需要将两个引用更改on_finished为;finished否则插件不会清理临时文件。可能还值得注意的是,由于下面列出的原因,如果运行失败,临时文件不会被删除。

要使用它,您需要一个与此类似的构建系统(根据需要修改命令;这是一个通用构建):

{
    "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"],
    },
}

这里的重要说明是targetand cancel,它将构建与插件提供的命令联系起来,working_dir它确保当前目录是当前文件所在的目录(因为这是预期input和文件所在的目录),output并且\\$temp_file用于引用包含结果代码的临时输出文件。

作为对此的说明,如果发生错误,错误中的行号将略微偏离,因为它们引用顶部有额外内容的文件,如果您导航到它,您将打开临时文件,即不是您可能应该编辑的那个。

所以,总而言之,片段可能是最安全、最快的方法。


推荐阅读