在 python 中为 Tcl 调用不同的解释器

Call different interpreter for Tcl in python

我希望 运行 一个带有不同解释器的 Tcl 脚本(OpenSees) from python itself, similar to this question,最实用的方法是什么?我已经尝试过 tkinter 和子进程例程,但据我所知我运行在纯 Tcl 中运行脚本,但没有任何反应(功能在 OpenSees 环境中定义)。 我试过通过 tkinter 调用我的 Tcl 脚本,但我终生无法弄清楚如何 运行 tcl 与另一个解释器,我试过的是:

for-test.tcl

proc fractional_while {j float_increment upper_limit} {
    while {$j < $upper_limit} {
        set j [expr $j + $float_increment]
    }
}
puts "time it took: [time {fractional_while 1 0.001 500} 1]"

python 文件

import tkinter
r = tkinter.Tk()
r.eval('source {for-test.tcl}')

我想做的是在 python 和 运行 中调用 Opensees 以下例程:

elastic-1dof-spectrum.tcl

model BasicBuilder -ndm 2 -ndf 3

set time_zero [clock clicks -millisec]

set node_restraint 1
set node_spring 2

...

set load_dir $x_direction
set x_mass 1
set elastic_modulus 2e6
set rotation_z 6

node $node_restraint 0 0 -mass 0 0 0
node $node_spring 0 0 -mass 0 0 0
fix $node_restraint 1 1 1

equalDOF $master_node $slave_node 1 2
geomTransf Linear $transf_tag

uniaxialMaterial Elastic $linear_elastic_mat_tag $elastic_modulus
element zeroLength 0 $node_restraint $node_spring -mat $linear_elastic_mat_tag -dir $rotation_z

set accel_series "Path -filePath acelerograma_85_ii.191 -dt $ground_motion_time_step -factor 1"
pattern UniformExcitation $load_tag $load_dir -accel $accel_series

set oscillator_length 1
set node_mass 3
set counter 1

while {$oscillator_length < 1000} {

set oscillator_length [expr $counter*0.1]
set node_mass [expr $counter + 2]

node $node_mass 0 $oscillator_length 
mass $node_mass $x_mass 0 0

element elasticBeamColumn $node_mass $node_spring $node_mass $area_column $elastic_modulus $inertia_column $transf_tag

set eigenvalue [eigen -fullGenLapack 1]
set period [expr 2*$pi/sqrt($eigenvalue)]

recorder EnvelopeNode -file results/acceleration-envelope-period-$period.out -time -node $node_mass -dof $x_direction accel
...

rayleigh [expr 2*$damping_ratio*$x_mass*$eigenvalue] 0 0 0
constraints Transformation 
# determines how dof constraits are treated and assigned
numberer Plain 
# numbering schemes are tied directly to the efficiency of numerical solvers
system BandGeneral
# defines the matricial numerical solving method based on the form of the stiffness matrix
test NormDispIncr 1e-5 10 0
integrator Newmark $gamma $beta
# defines the integrator for the differential movement equation
algorithm Newton
# solve nonlinear residual equation
analysis Transient
# for uniform timesteps in excitations
analyze [expr int($duration_motion/$time_step)] $time_step

incr counter
}

puts stderr "[expr {([clock clicks -millisec]-$time_zero)/1000.}] sec" ;# RS
wipe

这取决于 OpenSees 的构建方式及其提供的选项。

通常,嵌入 Tcl 的程序有两个主要选项,非常类似于 Python。

变体之一是有一个正常的 C/C++ 主程序和 link 到 Tcl 库,实际上 tclsh 做同样的事情,一个 shell可以执行 Tcl 命令并静态提供额外的命令。

变体二使用正常 tclsh 并且只是加载一些扩展模块来添加功能。如果是这种情况,如果它们足够相似,您通常可以简单地在 tkinter shell 中加载包,然后完成。

OpenSees 似乎是一个实现变体一的程序,一个包含一些外部不可用的额外命令的大愿望。所以你不能直接在 tkinter shell.

中加载代码

您有三个选择:

  1. 使用 Tcllib comm 包之类的东西在 Tkinter 和 OpenSees 之间进行通信 shell(参见 示例)
  2. 运行 通过 subprocess 打开并实施某种通信协议来发送您的命令。
  3. 修改 OpenSees 代码以将其构建为 Tcl 的可加载包并将其加载到您的 tkinter 进程中(可能很难)。

单线解决:

subprocess.call('Opensees elastic-1dof-spectrum.tcl', shell=True)