有没有办法在 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.io
Jario 提出的方法稍慢。
Jairo 给出的示例稍有变化:\process<filter>buffer
filter 模块提供的示例使用方括号代替花括号。为了完整起见,下面是完整的示例:
\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
是硬编码的,但您可以将其更改为python
,python2
或任何您的操作系统识别为有效 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