1

I am trying to call a tcl proc in a python program.

The tcl script starts with

proc scale_wigner-seitz_radii { } {

(I am not sure if I can put the full proc here, as this is a part of a licensed program).

This program is called by my python script:

#!/usr/bin/python3
import sys
from numpy import arange
from tempfile import mkstemp
from shutil import move, copy
from os import remove, close, mkdir, path
import Tkinter


def repll(file_path, pattern, subst):
    print(pattern)
    print(subst)
    print(file_path)
    r = Tkinter.Tk
    # fullpath = str(subst) + "/" + file_path
    fh, abs_path = mkstemp()
    with open(abs_path, "w") as new_file:
        with open(file_path, "r") as old_file:
            for line in old_file:
                new_file.write(line.replace(pattern.strip(),
                                            str(subst).strip()))
    r.tk.eval('source /home/rudra/WORK/xband/create_system_util.tcl')
    r.tk.eval('proc scale_wigner-seitz_radii')
    copy(abs_path, path.join(str(subst), file_path))


inpf = str(sys.argv[1])
a = []
print (inpf)
with open(inpf, "r") as ifile:
    for line in ifile:
        if line.startswith("lattice parameter A"):
            a = next(ifile, "")
            print(a)

for i in arange(float(a)-.10, float(a)+.10, 0.02):
    if not path.exists(str(i)):
        mkdir(str(i))
    repll(inpf, a, i)

I havn't make a minimal example, because this seems better than explaining in english.

At the very end of def repll, it is calling the tcl proc. I have never encountered a tcl script before, and found the calling process from this question. But when I am running this, I am getting error:

Traceback (most recent call last):
  File "xband.py", line 41, in <module>
    repll(inpf, a, i)
  File "xband.py", line 24, in repll
    r.tk.eval('source /home/rudra/WORK/xband/create_system_util.tcl')
AttributeError: class Tk has no attribute 'tk'

How I can solve this?

After Donal's Comment Thanks for your reply. After following your suggestion, I got same error from source line.

Traceback (most recent call last):
  File "xband.py", line 41, in <module>
    repll(inpf, a, i)
  File "xband.py", line 24, in repll
    r.tk.eval('/home/rudra/WORK/xband/create_system_util.tcl')
AttributeError: class Tk has no attribute 'tk'

Sorry if its silly, but since the tcl is in different file, I must source that first, right? And, as I said, this is the first tcl code I am looking at, please be elaborate.

Community
  • 1
  • 1
BaRud
  • 3,055
  • 7
  • 41
  • 89
  • You've not hit this bug yet, but `r.tk.eval('proc scale_wigner-seitz_radii')` is wrong. The Tcl `proc` command _defines_ commands; to call them, you just use the command name: `r.tk.eval('scale_wigner-seitz_radii')`. You'll need to sort your other bug out as well (and the fix for that might well also apply here). – Donal Fellows Sep 06 '15 at 07:41
  • _From a Tcl perspective,_ you have to first `source` the file, then invoke the procedure within it. This can be done in a single script call: `source /home/rudra/WORK/xband/create_system_util.tcl; scale_wigner-seitz_radii` (with a `;` to separate the two command calls). You also need to sort out the Python side of things, where it appears you are calling the `tk` method on the wrong entity. Do you need to instantiate the `Tk` class? – Donal Fellows Sep 06 '15 at 10:34
  • Hi Donal, if you have some free time, can I ping you? As I said, since the tcl is a part of licensed code, I am little sceptic to put it public – BaRud Sep 06 '15 at 10:39
  • I _really_ don't know Python well enough to help you properly. I've given all the Tcl help that you really need already (well, with this particular question anyway). And I tend to have rather busy days during the week… – Donal Fellows Sep 07 '15 at 00:00

1 Answers1

2

The problem seems to be this line:

r = Tkinter.Tk

My guess is, you think this is creating an instance of Tk, but you're merely saving a reference to the class rather than creating an instance of the class. When you instantiate it, the object that gets returned has an attribute named tk, which the object internally uses to reference the tcl interpreter. Since you aren't instantiating it, r (which points to Tk) has no such attribute.

To fix it, instantiate the class by adding parenthesis:

r = Tkinter.Tk()

r will now be a proper reference to a Tk object, and should have a tk attribute, and with that you can call eval on raw tcl code.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685