How to Call TCL Procedure using Python
Asked Answered
C

7

5

Using below code i can able to call all procedure in the Proc.tcl file ,but i want to call individually the procs like sum or sub ,Please let me know any other possibility to call it

My proc file program,

 puts "hello"
    proc sum {a b} {

     set c [expr $a + $b]
     puts "Addition: $c "
    }




  proc sub {a b} {

     set c [expr $a - $b]
     puts "Substraction: $c "
    }

My Main file program,

 import Tkinter
    import os
    r=Tkinter.Tk()
    r.tk.eval('source proc.tcl')
Cummerbund answered 8/5, 2013 at 11:50 Comment(0)
S
-4

instead of r.tk.eval('source proc.tcl')

try with os.system ('source proc.tcl') and import OS

Summitry answered 21/5, 2013 at 6:50 Comment(2)
Frankly, I don't see how this could possibly work. Can you elaborate on why this works?Pardon
@abhi: Yeah can you elaborate on this?. I know tcl interpreter is embedded in python. .tcl extension prompts the system() to use that interpreter? do I make any sense...Continuity
R
7

Just carry on as you are:

>>> import Tkinter
>>> r = Tkinter.Tk()
>>> r.tk.eval('proc sum {a b} {set c [expr {$a + $b}]; puts "Sum $c"; return $c}')
''
>>> r.tk.eval('sum 2 5')
Sum 7
'7'

So in your case, having sourced the tcl file you can just do r.tk.eval("sum 5 5") to call that procedure.

Note: always brace expr expressions in tcl. As in my example above.

Raymonraymond answered 8/5, 2013 at 12:23 Comment(0)
P
5

I do not know tcl, but this looks logical:

import tkinter
r=tkinter.Tk()
r.tk.eval('source proc.tcl')
r.tk.eval('sum 1 2')
r.tk.eval('sub 1 2')

>>> hello
>>> Addition: 3 
>>> Substraction: -1
Pia answered 8/5, 2013 at 12:19 Comment(2)
FYI. The module is Tkinter with capital T.Cockney
It actually depends of python version (tkinter in python 3)Adda
C
1

If you don't need the power of Tkinter, you can restructure proc.tcl a little and call the proc via subprocess:

proc.tcl:

proc sum {a b} {
    set c [expr $a + $b]
    puts "Addition: $c "
}

proc sub {a b} {
    set c [expr $a - $b]
    puts "Subtraction: $c "
}

eval $argv; # NOTE 1

caller.py:

import subprocess
import shlex

def tcl(command):
    command_line = shlex.split(command)
    output = subprocess.check_output(command_line)
    return output

print(tcl('tclsh proc.tcl sum 5 8'))
print(tcl('tclsh proc.tcl sub 19 8'))

Output of caller.py:

b'Addition: 13 \n'

b'Subtraction: 11 \n'

Discussion

  • Note 1: In the Tcl script, the line eval $argv takes what on the command line and execute it. It does not provide error checking at all, so potentially is dangerous. You will want to check the command line for malicious intention before executing it. What I have here is good for demonstration purpose.

  • The function tcl in caller.py takes a command line, split it, and call proc.tcl to do the work. It collects the output and return it to the caller. Again, for demonstration purpose, I did not include any error checking at all.

Update

If you are using python3 (most of us do), then to convert output from bytes to string, try

    output = subprocess.check_output(command_line, encoding="utf-8")
Cockney answered 8/5, 2013 at 20:14 Comment(2)
Note that this has the downside of having an extra process, the overhead to for inter-client communication etc. You should only fall back to such a thing if need it (unsafe code execution etc.)Dermot
This is perfect...I'm trying to demonstrate interop between tcl and python, and this lets me do it without needing to get Tkinter installed on our grid machines!Galanti
V
0

Use can use r.eval:

r.eval('source proc.tcl')
r.eval('sub {0} {1}'.format(a, b))

You should write just functions in proc.tcl.line like puts "hello" will be executed when evaluated with eval.

Valencia answered 2/1, 2016 at 11:49 Comment(0)
C
0
import subprocess

r = subprocess.check_output('tclsh proc.tcl', shell=True)
Carbuncle answered 25/5, 2017 at 18:9 Comment(1)
While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value.Edan
B
0

in Caller.py try:

import tkinter
import os

r = tkinter.Tk()
r.tk.evalfile('proc.tcl')
r.tk.eval('sum 1 2')
r.tk.eval('sub 1 2')

also, if you want to give numbers from your Python file, change like:

import tkinter
import os

r = tkinter.Tk()
r.tk.evalfile('proc.tcl')
x = 1
y = 2
r.tk.eval('sum {} {}'.format(x,y))
r.tk.eval('sub {} {}'.format(x,y))
Binford answered 5/12, 2021 at 14:30 Comment(0)
S
-4

instead of r.tk.eval('source proc.tcl')

try with os.system ('source proc.tcl') and import OS

Summitry answered 21/5, 2013 at 6:50 Comment(2)
Frankly, I don't see how this could possibly work. Can you elaborate on why this works?Pardon
@abhi: Yeah can you elaborate on this?. I know tcl interpreter is embedded in python. .tcl extension prompts the system() to use that interpreter? do I make any sense...Continuity

© 2022 - 2024 — McMap. All rights reserved.