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

Is it possible to see if a package is loaded

71 views
Skip to first unread message

Cecil Westerhof

unread,
Jan 22, 2018, 8:14:05 PM1/22/18
to
I have a function to fetch all fonts. But this can of-course only be
called if Tk is loaded. Is there a way to verify that a package (in
this case Tk) is loaded?

I do not want to use:
package require Tk

Because that creates a window if Tk was not loaded.

--
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof

Rich

unread,
Jan 22, 2018, 9:14:19 PM1/22/18
to
Cecil Westerhof <Ce...@decebal.nl> wrote:
> I have a function to fetch all fonts. But this can of-course only be
> called if Tk is loaded. Is there a way to verify that a package (in
> this case Tk) is loaded?
>
> I do not want to use:
> package require Tk
>
> Because that creates a window if Tk was not loaded.

"man package"

Specifically read the part about "present".

Then experiment in a Tcl REPL to see how it works.

Cecil Westerhof

unread,
Jan 22, 2018, 10:59:05 PM1/22/18
to
Rich <ri...@example.invalid> writes:

> Cecil Westerhof <Ce...@decebal.nl> wrote:
>> I have a function to fetch all fonts. But this can of-course only be
>> called if Tk is loaded. Is there a way to verify that a package (in
>> this case Tk) is loaded?
>>
>> I do not want to use:
>> package require Tk
>>
>> Because that creates a window if Tk was not loaded.
>
> "man package"

Sadly the man pages are not installed on my system. But luckily I
found:
http://wiki.tcl.tk/9943

For one reason or another it does not work, but I have a starting
point now.

Thanks.


> Specifically read the part about "present".
>
> Then experiment in a Tcl REPL to see how it works.

Rich

unread,
Jan 22, 2018, 11:01:27 PM1/22/18
to
Cecil Westerhof <Ce...@decebal.nl> wrote:
> Rich <ri...@example.invalid> writes:
>
>> Cecil Westerhof <Ce...@decebal.nl> wrote:
>>> I have a function to fetch all fonts. But this can of-course only be
>>> called if Tk is loaded. Is there a way to verify that a package (in
>>> this case Tk) is loaded?
>>>
>>> I do not want to use:
>>> package require Tk
>>>
>>> Because that creates a window if Tk was not loaded.
>>
>> "man package"
>
> Sadly the man pages are not installed on my system.

I would highly recommend you install the man pages. That is unless
your 'system' is windows, then installing them likely won't work at
all.


> But luckily I found:
> http://wiki.tcl.tk/9943
>
> For one reason or another it does not work, but I have a starting
> point now.

Care to elaborate on "does not work"?

Cecil Westerhof

unread,
Jan 23, 2018, 1:14:04 AM1/23/18
to
Rich <ri...@example.invalid> writes:

> Cecil Westerhof <Ce...@decebal.nl> wrote:
>> Rich <ri...@example.invalid> writes:
>>
>>> Cecil Westerhof <Ce...@decebal.nl> wrote:
>>>> I have a function to fetch all fonts. But this can of-course only be
>>>> called if Tk is loaded. Is there a way to verify that a package (in
>>>> this case Tk) is loaded?
>>>>
>>>> I do not want to use:
>>>> package require Tk
>>>>
>>>> Because that creates a window if Tk was not loaded.
>>>
>>> "man package"
>>
>> Sadly the man pages are not installed on my system.
>
> I would highly recommend you install the man pages. That is unless
> your 'system' is windows, then installing them likely won't work at
> all.

I was planning to do that. I wanted to ask on the Debian list how to
do it. I find it a bit strange because of all other packages the man
pages are installed. But it was very easy: I just had to install
tcl-doc.


>> But luckily I found:
>> http://wiki.tcl.tk/9943
>>
>> For one reason or another it does not work, but I have a starting
>> point now.
>
> Care to elaborate on "does not work"?

I should have evaluate further. :'-(

For one thing, if I enter:
expr ![catch {package present Tk}]

I get a secondary prompt.


When I define the function in the interactive shell and call it, I
would expect to get False (or 0), but I get:
in
while evaluating {is_Tk_present }

But when I define it in a script and use it in the script, it works as
expected.

Christian Gollwitzer

unread,
Jan 23, 2018, 1:34:32 AM1/23/18
to
Am 23.01.18 um 04:44 schrieb Cecil Westerhof:
> Rich <ri...@example.invalid> writes:
>
>> Cecil Westerhof <Ce...@decebal.nl> wrote:
>>> I have a function to fetch all fonts. But this can of-course only be
>>> called if Tk is loaded. Is there a way to verify that a package (in
>>> this case Tk) is loaded?
>>>
>>> I do not want to use:
>>> package require Tk
>>>
>>> Because that creates a window if Tk was not loaded.
>>
>> "man package"
>
> Sadly the man pages are not installed on my system. But luckily I
> found:
> http://wiki.tcl.tk/9943
>

The wiki is a nice place, if you want the "real" documentation try the
pages at

https://www.tcl.tk/man/tcl8.6/

of which

https://www.tcl.tk/man/tcl8.6/TclCmd/package.htm

should answer all your questions.

Christian

Cecil Westerhof

unread,
Jan 23, 2018, 3:44:05 AM1/23/18
to
Cecil Westerhof <Ce...@decebal.nl> writes:

> For one thing, if I enter:
> expr ![catch {package present Tk}]
>
> I get a secondary prompt.
>
>
> When I define the function in the interactive shell and call it, I
> would expect to get False (or 0), but I get:
> in
> while evaluating {is_Tk_present }
>
> But when I define it in a script and use it in the script, it works as
> expected.

If I define (a bit more general) function in a package and use that in
the interactive shell it does work. For one reason or another there is
a difference between defining in the interactive shell and a package.
I also added braces around the expression. ;-)
The code:
proc ::dcblUtilities::isPackagePresent {package} {
expr {![catch {package present ${package}}]}
}

I added it to the WiKi page.

Rich

unread,
Jan 23, 2018, 6:44:36 AM1/23/18
to
Cecil Westerhof <Ce...@decebal.nl> wrote:
> Rich <ri...@example.invalid> writes:
>
>> Cecil Westerhof <Ce...@decebal.nl> wrote:
>>> Rich <ri...@example.invalid> writes:
>>>
>>>> Cecil Westerhof <Ce...@decebal.nl> wrote:
>>>>> I have a function to fetch all fonts. But this can of-course only be
>>>>> called if Tk is loaded. Is there a way to verify that a package (in
>>>>> this case Tk) is loaded?
>>>>>
>>>>> I do not want to use:
>>>>> package require Tk
>>>>>
>>>>> Because that creates a window if Tk was not loaded.
>>>>
>>>> "man package"
>>>
>>> Sadly the man pages are not installed on my system.
>>
>> I would highly recommend you install the man pages. That is unless
>> your 'system' is windows, then installing them likely won't work at
>> all.
>
> I was planning to do that. I wanted to ask on the Debian list how to
> do it. I find it a bit strange because of all other packages the man
> pages are installed. But it was very easy: I just had to install
> tcl-doc.

Ah, yes, Debian, with their silly split of X, X-dev, and X-doc
packages.

One of the many reasons why I run Slackware. Slackware is sensible.
When you install X, you get all of X, X-dev, and X-doc all at once. No
silliness.

>> Care to elaborate on "does not work"?
>
> I should have evaluate further. :'-(
>
> For one thing, if I enter:
> expr ![catch {package present Tk}]

Why in the world would your first 'test' be to run it inside a catch,
and run that inside an expr?

If you are running from a REPL, start by /just running the bare
command/:

$ rlwrap tclsh
% package present Tk
package Tk is not present
%

Your catch hid the return value string from 'package present' and only
returned to you "1", which the ! then flipped to "0", which expr
evaluated as false (and since 'false' from expr returns nothing, a prompt
is reasonable there).

> I get a secondary prompt.

No, you should have been returned to the main prompt:

% expr ![catch {package present Tk}]
0
%

The 'secondary' prompt looks different (empty, unless you've changed your
local defaults):

% expr {1+1

> When I define the function in the interactive shell and call it, I
> would expect to get False (or 0), but I get:
> in
> while evaluating {is_Tk_present }

Again, why did you start out with a complex monster in the REPL first.
It is best to build up from the basic building blocks one block at a
time, then you see what happens at each step:

$ rlwrap tclsh
% package present Tk
package Tk is not present
% catch {package present Tk} r
1
% set r
package Tk is not present
% expr ![catch {package present Tk} r]
0
% set r
package Tk is not present
%

And using rlwrap (since Tcl's default REPL has not history) is 'really
useful' because it adds full readline history/editing around commands
that don't offer the same themselves.

As for your 'in', since you failed to "show your work" for
"is_Tk_present", and I *can't read your mind over usenet*, I can only
speculate as to what went wrong.

Rich

unread,
Jan 23, 2018, 6:48:29 AM1/23/18
to
Cecil Westerhof <Ce...@decebal.nl> wrote:
> If I define (a bit more general) function in a package and use that in
> the interactive shell it does work. For one reason or another there is
> a difference between defining in the interactive shell and a package.
> I also added braces around the expression. ;-)
> The code:
> proc ::dcblUtilities::isPackagePresent {package} {
> expr {![catch {package present ${package}}]}
> }

Interactive shell:

$ rlwrap tclsh
% proc ::dcblUtilities::isPackagePresent {package} {
expr {![catch {package present ${package}}]}
}
can't create procedure "::dcblUtilities::isPackagePresent": unknown namespace
% proc isPackagePresent {package} {
expr {![catch {package present ${package}}]}
}
% isPackagePresent Tk
0
%

No difference (note I left the first error message in to show what
happens when one forgets to initially define the namespace in the
REPL. But any difference in defining a proc between the two is almost
always the result of a typo in the REPL, not because it is in the REPL.

Cecil Westerhof

unread,
Jan 23, 2018, 9:28:07 AM1/23/18
to
The proc is of-course sitting in a package that I include with:
package require dcblUtilities

namespace import ::dcblUtilities::*


This is very strange: when I define the proc in my shell I get:
$ proc isPackagePresent {package} {
> expr {![catch {package present ${package}}]}
> }
tclsh8.6 [Tue, 23 Jan 15:08:03 cecil@munus:~/Databases]
$ isPackagePresent Tk
in
while evaluating {isPackagePresent Tk}

The difference being that I just use:
tclsh

And have the following in my ~/.tclshrc:
package require dcblUtilities
package require dcblUtilitiesExtra

namespace import ::dcblUtilities::*

if {${tcl_interactive}} {
package require tclreadline

namespace path {::tcl::mathop ::tcl::mathfunc}

set auto_noexec 1

proc ::tclreadline::prompt1 {} {
set colour1 [getColour redLight]
set colour2 [getColour white]
set colour3 [getColour nothing]
set user $::tcl_platform(user)
if {${user} eq "root"} {
set temp ${colour1}
set colour1 ${colour2}
set colour2 ${temp}
}
set currentDir [regsub "^/home/${user}" [pwd] ~]
set dateTime [clock format [clock seconds] -format "%a, %e %b %T"]
set host [lindex [split [info hostname] "."] 0]
format "%s%s %s\[%s %s@%s:%s\]\n$ %s" \
${colour1} \
tclsh${::tcl_version} \
${colour2} \
${dateTime} \
${user} \
${host} \
${currentDir} \
${colour3}
}

::tclreadline::Loop
}

When using:
rlwrap tclsh

I had the same error.
But when I remove ~/.tclshrc I get the same result as you. So it looks
like it that my ~/.tclshrc messes things up for me.

Anyone an idea what could be the problem in my ~/.tclshrc?

Cecil Westerhof

unread,
Jan 23, 2018, 9:44:06 AM1/23/18
to
Rich <ri...@example.invalid> writes:

> Cecil Westerhof <Ce...@decebal.nl> wrote:
>> Rich <ri...@example.invalid> writes:
>>
>>> Cecil Westerhof <Ce...@decebal.nl> wrote:
>>>> Rich <ri...@example.invalid> writes:
>>>>
>>>>> Cecil Westerhof <Ce...@decebal.nl> wrote:
>>>>>> I have a function to fetch all fonts. But this can of-course only be
>>>>>> called if Tk is loaded. Is there a way to verify that a package (in
>>>>>> this case Tk) is loaded?
>>>>>>
>>>>>> I do not want to use:
>>>>>> package require Tk
>>>>>>
>>>>>> Because that creates a window if Tk was not loaded.
>>>>>
>>>>> "man package"
>>>>
>>>> Sadly the man pages are not installed on my system.
>>>
>>> I would highly recommend you install the man pages. That is unless
>>> your 'system' is windows, then installing them likely won't work at
>>> all.
>>
>> I was planning to do that. I wanted to ask on the Debian list how to
>> do it. I find it a bit strange because of all other packages the man
>> pages are installed. But it was very easy: I just had to install
>> tcl-doc.
>
> Ah, yes, Debian, with their silly split of X, X-dev, and X-doc
> packages.

But as far as I know Debian does this not with other packages. Or
maybe it installs the manpages only for the default packages. I do not
use man a lot.


> One of the many reasons why I run Slackware. Slackware is sensible.
> When you install X, you get all of X, X-dev, and X-doc all at once. No
> silliness.

I did use Slackware very long ago when I just wanted to see other
versions of Linux. But overall I like Debian.


>>> Care to elaborate on "does not work"?
>>
>> I should have evaluate further. :'-(
>>
>> For one thing, if I enter:
>> expr ![catch {package present Tk}]
>
> Why in the world would your first 'test' be to run it inside a catch,
> and run that inside an expr?

Because package present Tk also gave an error so I thought lets do
exactly the same. It turns out it is because I not use rlwrap and
there is probably an error in my ~/.tclshrc. See my other reply.

Cecil Westerhof

unread,
Jan 23, 2018, 9:59:06 AM1/23/18
to
I found the problem. In my ~/.tclshrc I have:
::tclreadline::Loop

And this messes things up. I create a separate thread for that.

Ralf Fassel

unread,
Jan 23, 2018, 11:14:15 AM1/23/18
to
* Cecil Westerhof <Ce...@decebal.nl>
| > Interactive shell:
| >
| > $ rlwrap tclsh
--<snip-snip>--
| I found the problem. In my ~/.tclshrc I have:
| ::tclreadline::Loop

Just guessing, assuming package tclreadline adds readline-like editing
to tclsh: either use tclreadline OR rlwrap, not both.

R'

Rich

unread,
Jan 23, 2018, 12:20:35 PM1/23/18
to
What little I know of Debian (which comes from helping a buddy with his
Ubuntu system), Debian does this silly split for *every* single tool.

I've heard folks 'explain' it away as "but if I only want to use my
system, but never develop on it, why should I take up the disk space
for those -dev and -doc packages?". Which in the days of 250MB drives
might have been a valid complaint. In todays world of terabyte drives,
it is not worth the trouble anymore.

>>>> Care to elaborate on "does not work"?
>>>
>>> I should have evaluate further. :'-(
>>>
>>> For one thing, if I enter:
>>> expr ![catch {package present Tk}]
>>
>> Why in the world would your first 'test' be to run it inside a catch,
>> and run that inside an expr?
>
> Because package present Tk also gave an error so I thought lets do
> exactly the same. It turns out it is because I not use rlwrap and
> there is probably an error in my ~/.tclshrc. See my other reply.

Hmm, interesting. You found a cause (the call into Loop within
readline).

As I don't use tclreadline and instead just let rlwrap handle it, I
don't know why this might be happening.

Cecil Westerhof

unread,
Jan 23, 2018, 12:44:04 PM1/23/18
to
Oops, that happens when you do things to fast.

I do not use rlwrap (that was used by others). I have
::tclreadline::Loop in my ~/.tclshrc so I can just use 'tclsh' instead
of 'rlwrap tclsh'.

Cecil Westerhof

unread,
Jan 23, 2018, 1:44:06 PM1/23/18
to
Rich <ri...@example.invalid> writes:

>> Because package present Tk also gave an error so I thought lets do
>> exactly the same. It turns out it is because I not use rlwrap and
>> there is probably an error in my ~/.tclshrc. See my other reply.
>
> Hmm, interesting. You found a cause (the call into Loop within
> readline).
>
> As I don't use tclreadline and instead just let rlwrap handle it, I
> don't know why this might be happening.

Ted Nolan provided the solution: '!' is the history interpolation
character. I changed:
expr {![catch {package present Tk}]}

to:
expr {! [catch {package present Tk}]}

and problem solved.

Ricardo kozmate.net

unread,
Jan 23, 2018, 5:09:10 PM1/23/18
to
Em 23/01/18 03:44, Cecil Westerhof escreveu:
> Sadly the man pages are not installed on my system.

You may look at <https://www.tcl.tk/man/> for (just about) the same.
(And more)

--
{ricardo from kozmate.net}

keithv

unread,
Jan 24, 2018, 9:16:19 PM1/24/18
to
On Monday, January 22, 2018 at 5:14:05 PM UTC-8, Cecil Westerhof wrote:
> I have a function to fetch all fonts. But this can of-course only be
> called if Tk is loaded. Is there a way to verify that a package (in
> this case Tk) is loaded?

For tk, I just do:
if {[info exists tk_version]} {...}

Cecil Westerhof

unread,
Jan 25, 2018, 12:28:06 AM1/25/18
to
That is a nice one. I already wrote a function isPackagePresent, but
in the case of Tk this is (in my opinion) a much better solution.

Thanks.
0 new messages