Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Speed up the exec

75 views
Skip to first unread message

Chang LI

unread,
Nov 26, 2000, 1:39:18 AM11/26/00
to
The following code is slow when the ls is large

set ls {s1.tcl s2.tcl}
foreach e $ls {
exec tclsh83.exe $e
}

each .tcl code is independent.

Is there a way to speed up the exec?
At least I do not need to load the tcl83.dll every times.

Chang LI
Neatware

Jeffrey Hobbs

unread,
Nov 26, 2000, 3:00:00 AM11/26/00
to Chang LI

Do you have to exec? Can't you just create these in separate
interpreters, sourcing them in? You'd have to protect against
'exit' and maybe a few other calls, but it's a simple, powerful
mechanism for what you need to do.

--
Jeffrey Hobbs The Tcl Guy
jeff.hobbs at acm.org

Chang LI

unread,
Nov 26, 2000, 3:00:00 AM11/26/00
to

Jeffrey Hobbs wrote in message <3A20CE88...@ajubasolutions.com>...
>Do you have to exec? Can't you just create these in separate
>interpreters, sourcing them in? You'd have to protect against
>'exit' and maybe a few other calls, but it's a simple, powerful
>mechanism for what you need to do.
>

That is my code with interp

set ls {s1.tcl s2.tcl}
foreach e $ls {

interp create foo
interp eval foo source $e
interp delete foo
}

The result was weird. Only first script be executed. In the s1.tcl and
s2.tcl there are source commands. In the same way

foreach e $ls {
source $e
}

only first script be executed as well.


Chang LI
Neatware

Hemang Lavana

unread,
Nov 26, 2000, 3:00:00 AM11/26/00
to
Chang LI wrote:
> ...

> That is my code with interp
>
> set ls {s1.tcl s2.tcl}
> foreach e $ls {
> interp create foo
> interp eval foo source $e
> interp delete foo
> }
>
> The result was weird. Only first script be executed. In the s1.tcl and
> s2.tcl there are source commands. In the same way

Your script file s1.tcl may have some weird commands in it - perhaps it
has a return stmt in it. The following works for me as expected:

$ ls
main.tcl s1.tcl s2.tcl

$ cat s1.tcl
puts "sourcing s1.tcl ..."

$ cat s2.tcl
puts "sourcing s2.tcl ..."

$ cat main.tcl
# main.tcl


set ls {s1.tcl s2.tcl}
foreach e $ls {

interp create foo
interp eval foo source $e
interp delete foo
}

$ tclsh main.tcl
sourcing s1.tcl ...
sourcing s2.tcl ...

Hemang.

Chang LI

unread,
Nov 27, 2000, 1:25:14 AM11/27/00
to

Hemang Lavana wrote in message <3A21CA8A...@cisco.com>...

>> The result was weird. Only first script be executed. In the s1.tcl and
>> s2.tcl there are source commands. In the same way
>
>Your script file s1.tcl may have some weird commands in it - perhaps it
>has a return stmt in it. The following works for me as expected:
>

There is no return but there are source and package.
In theory it should work. However the exec worked fine.

Chang

>$ ls
>main.tcl s1.tcl s2.tcl
>
>$ cat s1.tcl
>puts "sourcing s1.tcl ..."
>
>$ cat s2.tcl
>puts "sourcing s2.tcl ..."
>
>$ cat main.tcl
># main.tcl

>set ls {s1.tcl s2.tcl}
>foreach e $ls {

Hemang Lavana

unread,
Nov 27, 2000, 3:00:00 AM11/27/00
to
Chang LI wrote:
> ...

> There is no return but there are source and package.
> In theory it should work. However the exec worked fine.

I can't say much without knowing the script files s1.tcl or s2.tcl, but
I have been using the following script without any problems for all my
applications. The only problem I have faced is that the alias to exit
doesn't work properly sometimes. IIRC, it happens when you have tcl
commands after exit stmt in your script. Since invoking exit command
deletes the interpreter, it gives out an error message because it still
tries to evaluate the remaining tcl commands (after exit) but finds no
interpreter to execute it in.

Hemang.

----
Here's the script that I use:

## execInterp.tcl
## {[( Use vi's "%" cmd to match corresponding braces

namespace eval execInterp {
# Usage:
# execInterp::ExecTclCmd "app1.tcl input1 input2 output"
namespace export ExecTclCmd

# Usage:
# execInterp::ExecTkCmd "app2.tk input"
namespace export ExecTkCmd

# An array variable to store the interpreter name
# for the sourced file
variable vars

##############
# Execute the specified file with tcl
#
proc ExecTclCmd {cmd} { ;#[(
set fName [lindex $cmd 0]
set cmdargs [lrange $cmd 1 end]
launchTclTkAppln tcl $fName $cmdargs
} ;#]) End of proc ExecTclCmd

##############
# Execute the specified file with tk/wish
#
proc ExecTkCmd {cmd} { ;#[(
set fName [lindex $cmd 0]
set cmdargs [lrange $cmd 1 end]
launchTclTkAppln tk $fName $cmdargs
} ;#]) End of proc ExecTkCmd

##############
# Execute the specified file with either tclsh or wish
#
proc launchTclTkAppln {type fName cmdargs} {
variable vars

# Uncomment this line for debugging
# puts type=$type,fName=$fName,cmdargs=$cmdargs
if {$fName == ""} {return}
if {![file exists $fName]} {
puts stderr "File not found: $fName"
return
}
if {[info exists vars($fName)]} {
interp delete $vars($fName)
}

# Create a new interpreter and load tk if it is a wish application
set vars($fName) [interp create]
switch -exact -- $type {
"wish" -
"tk" {load {} Tk $vars($fName)}
default {}
} ;# End of switch stmt

# Now source the application in a new interpreter
set nsc [namespace current]
$vars($fName) alias exit ${nsc}::exitChldAppln $fName
$vars($fName) eval set argv0 [list $fName]
$vars($fName) eval set argv [list $cmdargs]
$vars($fName) eval set argc [llength $cmdargs]
$vars($fName) eval source [list $fName]
switch -exact -- $type {
"tcl" {
if {[info exists vars($fName)]} {
$vars($fName) eval exit
}
}
"wish" -
"tk" {# User needs to exit this application from gui}
default {}
} ;# End of switch stmt
} ;# End of proc launchTclTkAppln

##############
# Exit an invoked application by deleting the child interpreter
#
proc exitChldAppln {fName {status 0}} {
variable vars

interp delete $vars($fName)
set vars($fName) exiting
unset vars($fName)
} ;# End of proc exitChldAppln

} ;# End of namespace execInterp

## )]} Use vi's "%" cmd to match corresponding braces
## execInterp.tcl

Don Porter

unread,
Nov 27, 2000, 3:00:00 AM11/27/00
to
Hemang Lavana <hla...@cisco.com> wrote:
> I have been using the following script without any problems for all my
> applications. The only problem I have faced is that the alias to exit
> doesn't work properly sometimes. IIRC, it happens when you have tcl
> commands after exit stmt in your script. Since invoking exit command
> deletes the interpreter, it gives out an error message because it still
> tries to evaluate the remaining tcl commands (after exit) but finds no
> interpreter to execute it in.

Several months ago I started a Wiki page on this problem:

http://www.purl.org/thecliff/tcl/wiki/894.html

I still haven't completed it yet, but it explains the problem
pretty thoroughly and offers a solution that should provide a
viable work around for most cases.

--
| Don Porter Mathematical and Computational Sciences Division |
| donald...@nist.gov Information Technology Laboratory |
| http://math.nist.gov/~DPorter/ NIST |
|______________________________________________________________________|

Hemang Lavana

unread,
Nov 28, 2000, 3:00:00 AM11/28/00
to
Don Porter wrote:
> ...

> Several months ago I started a Wiki page on this problem:
>
> http://www.purl.org/thecliff/tcl/wiki/894.html
>
> I still haven't completed it yet, but it explains the problem
> pretty thoroughly and offers a solution that should provide a
> viable work around for most cases.

That's great. Similar to the `exit' problem that you mention in "Take
1", there is one more problem with multiple interps - `cd' command is
global across interpreters, the following example illustrates this
problem (tcl8.3.2):

% pwd
C:/PROGRA~1/TCL
% interp create x
x
% interp create y
y
% x eval pwd
C:/PROGRA~1/TCL
% y eval pwd
C:/PROGRA~1/TCL
% x eval [list cd ..]
% x eval pwd
C:/PROGRA~1
% y eval pwd
C:/PROGRA~1
% exit

The current solution to this problem is similar to your "Take 4" - store
the path for each interp in a variable and alias all tcl commands
related to filepaths, such as cd, exec, file, glob, open, pwd, etc to a
alias-processor that (1) changes to the current directory for the
calling interpreter, (2) invokes the relevant original command, (3)
changes the current directory back to original path, (4) return the
results. This solution probably does not resolve all cases that can
occur and is also not very elegant.

I wonder if the threads package will help overcome these problems (I
have never tried it though). All I want is a cross-platform mechanism
for invoking other tcl scripts from tcl. "exec" is not cross-platform
due to different syntax required on unix, windows and it is not
available on mac. This problem is a subset of the more generic need of
having a new higher level cross-platform command that does the job of
"exec" or "apple-script" with the correct syntax depending on the
platform. This issue and need was discussed sometime back in clt.

Hemang.

Jeffrey Hobbs

unread,
Nov 28, 2000, 3:00:00 AM11/28/00
to Hemang Lavana
Hemang Lavana wrote:
>
> Don Porter wrote:
> > ...
> > Several months ago I started a Wiki page on this problem:
> >
> > http://www.purl.org/thecliff/tcl/wiki/894.html
> >
> > I still haven't completed it yet, but it explains the problem
> > pretty thoroughly and offers a solution that should provide a
> > viable work around for most cases.
>
> That's great. Similar to the `exit' problem that you mention in "Take
> 1", there is one more problem with multiple interps - `cd' command is
> global across interpreters, the following example illustrates this
> problem (tcl8.3.2):

This is one I've lived with ever since starting tkcon. The fact is
that the process has only one cwd (getcwd()), so all the interps have
to share it. This is just a unixism you have to work with. It may
get worse if multiple threads of one process have the same limitation,
because it means that you really can cd in one interp, jump context
to another interp and cd there, then jump context back and try to do
a file open... Hmmm, almost to the point where you'd want Tcl to
handle the magic under the covers.

0 new messages