在 ConTeXt 中执行 Python

在 ConTeXt 中执行 Python

有没有办法在 ConTeXt 文档中执行 Python 代码?在 LaTeX 中我们有 pythontex。

例如 :

\starttext
\startpython
print("text")
\stoppython
text
\stoptext

答案1

为了进行比较,下面是使用以下方法实现与 Jairo 的解决方案类似的方法:t 过滤器模块。

\usemodule[filter]
\defineexternalfilter
  [python]
  [
    filtercommand={python \externalfilterinputfile\space > \externalfilteroutputfile},
    output={\externalfilterbasefile.tex},
    cache=yes,
    % directory=temp, if you want to redirect all temp files to a subdir
  ]

是的,就是这样!该选项cache=yes会缓存结果,因此只有当缓冲区或环境的内容发生变化时,python 才会重新运行。您还可以将输出存储在临时目录中,这样结果就看不见了。请参阅过滤器模块的文档以了解其他功能(包括正确的 XML 导出!)

t-filter 模块将所有内容写入外部文件,因此可能比pipe.ioJario 提出的方法稍慢。

Jairo 给出的示例稍有变化:\process<filter>bufferfilter 模块提供的示例使用方括号代替花括号。为了完整起见,下面是完整的示例:

\usemodule[filter]
\defineexternalfilter
  [python]
  [
    filtercommand={python \externalfilterinputfile\space > \externalfilteroutputfile},
    output={\externalfilterbasefile.tex},
    cache=yes,
    % directory=temp, if you want to redirect all temp files to a subdir
  ]


\starttext
\startimath
\startpython
import math
print(math.cos(3.141592))
\stoppython
\stopimath

\startpython
Sentence1 = "{fmt} is {adj}".format(fmt="Con\\TeX t", adj="great")
print(Sentence1)
\stoppython

%https://www.programiz.com/python-programming/examples
\startbuffer[hcf]
# Python program to find H.C.F of two numbers

# define a function
def compute_hcf(x, y):

# choose the smaller number
    if x > y:
        smaller = y
    else:
        smaller = x
    for i in range(1, smaller+1):
        if((x % i == 0) and (y % i == 0)):
            hcf = i 
    return hcf

num1 = 54 
num2 = 24

print("The H.C.F. is", compute_hcf(num1, num2))
\stopbuffer

\startbuffer[powersof2]
# Display the powers of 2 using anonymous function

terms = 10

# Uncomment code below to take input from the user
# terms = int(input("How many terms? "))

# use anonymous function
result = list(map(lambda x: 2 ** x, range(terms)))

print("The total terms are:",terms)
for i in range(terms):
   print("2 raised to power",i,"is",result[i])
\stopbuffer

%Adapted from
%https://www.w3schools.com/python/
\startbuffer[anotherpython]
b = "I prefer Lua over Python"
print(b[9:])
a = ("d", "e", "k", "n", "u", "t", "h")
x = slice(2)
print(a[x])
\stopbuffer
\processpythonbuffer[hcf]

\processpythonbuffer[anotherpython]

\processpythonfile{abc.py}

\startlines
\processpythonbuffer[powersof2]
\stoplines

\stoptext

答案2

有一个快速而肮脏的解决方案,使用緩衝器. 一些评论:

  • 我定义了 (1)\startpython ... \stoppython立即处理 Python 内容,(2) 使用\processpythonbuffer函数将缓冲区作为 Python 文件进行处理print,以及 (3)\processpythonfile执行与 (1) 相同的操作,但使用文件而不是缓冲区。(1) 用于获取结果事实本身,而最后几个则有助于延迟或重用 Python 代码片段。我意识到你问的是第一个,所以最好晚点...
  • 对于缓冲区,我创建了一个名为的临时文件ctxpythonbuffer.py,该文件被执行后被删除。除非您有一个这样命名的文件,否则您不会遇到任何问题。我会使用\savebuffer,但它似乎比较慢。
  • 我使用缓冲区和文件io.popen来捕获命令行输出。我不知道 Python 是否与 Lua 绑定,反之亦然,但你可以做进一步的研究。顺便说一句,如果你想深入了解,你可能会发现 Luigi Scarso 的实验 LuaTeX lunatic 很有趣。详细信息这里这里。我不会,因为我不喜欢 Python。
  • python3是硬编码的,但您可以将其更改为pythonpython2或任何您的操作系统识别为有效 Python 调用的命令。如果您想添加版本或其他设置之间的切换,CLD 手册是通过 Lua 编写自己的命令的一个很好的起点。奖金:如果你还没有接受 Lua,那么你应该学习另一种编程语言;)
#abc.py
#Dummy file
print("a")
print("b")
print("c")
%\setuppapersize[A6]
\startluacode

userdata = userdata or {}
local implement = interfaces.implement
local suffix = ".py"

--Adapted from:
--https://gist.github.com/dukeofgaming/453cf950abd99c3dc8fc
local pythonbuffer = 
function(file)
    local handle = assert(io.popen(string.format("python3 %s", file), 'r'))
    local output = assert(handle:read('*a'))
    handle:close()
    return output
end

userdata.processpythonbuffer =
function (content) 
    local name = "ctxpythonbuffer.py"
    io.savedata(name,content)
    result = pythonbuffer(name)
    os.remove(name)
    return result
end

userdata.processpythonfile =
function (name)
    assert(name ~= "", "File name needed")
    name = name:find(suffix.."$") and name or name..suffix
    return pythonbuffer(name)
end

implement{
    name        = "processpythonbuffer",
    public      = true,
    arguments   = {"string"},
    actions     = function(s)
        context(userdata.processpythonbuffer(buffers.getcontent(s)))
    end
}

implement{
    name        = "processpythonfile",
    public      = true,
    arguments = {"string"},
    actions     = function(s)
        context(userdata.processpythonfile(s))
    end
}

\stopluacode
%Buffer name isn't really important
%You could use another, less verbose...
\def\startpython%
    {\def\stoppython{\processpythonbuffer{ctx_python_buffer}}%
    \dostartbuffer[ctx_python_buffer][startpython][stoppython]}
\starttext
\startimath
\startpython
import math
print(math.cos(3.141592))
\stoppython
\stopimath

\startpython
Sentence1 = "{fmt} is {adj}".format(fmt="Con\\TeX t", adj="great")
print(Sentence1)
\stoppython

%https://www.programiz.com/python-programming/examples
\startbuffer[hcf]
# Python program to find H.C.F of two numbers

# define a function
def compute_hcf(x, y):

# choose the smaller number
    if x > y:
        smaller = y
    else:
        smaller = x
    for i in range(1, smaller+1):
        if((x % i == 0) and (y % i == 0)):
            hcf = i 
    return hcf

num1 = 54 
num2 = 24

print("The H.C.F. is", compute_hcf(num1, num2))
\stopbuffer

\startbuffer[powersof2]
# Display the powers of 2 using anonymous function

terms = 10

# Uncomment code below to take input from the user
# terms = int(input("How many terms? "))

# use anonymous function
result = list(map(lambda x: 2 ** x, range(terms)))

print("The total terms are:",terms)
for i in range(terms):
   print("2 raised to power",i,"is",result[i])
\stopbuffer

%Adapted from
%https://www.w3schools.com/python/
\startbuffer[anotherpython]
b = "I prefer Lua over Python"
print(b[9:])
a = ("d", "e", "k", "n", "u", "t", "h")
x = slice(2)
print(a[x])
\stopbuffer
\processpythonbuffer{hcf}

\processpythonbuffer{anotherpython}

\processpythonfile{abc}

%\startlines ... \stoplines is the rough equivalent of Plain/LaTeX \obeylines
\startlines
\processpythonbuffer{powersof2}
\stoplines

\stoptext

在此处输入图片描述

相关内容