无法从用 Tcl 编写的应用程序中找到包
Can't find package from application written in Tcl
感谢大家的指点,对问题的理解又加深了一点。变量:
thufir@dur:~/tcl/packages$
thufir@dur:~/tcl/packages$ echo 'puts $auto_path' | tclsh
/usr/share/tcltk/tcl8.6 /usr/share/tcltk /usr/lib /usr/local/lib/tcltk /usr/local/share/tcltk /usr/lib/tcltk/x86_64-linux-gnu /usr/lib/tcltk /usr/lib/tcltk/tcl8.6
thufir@dur:~/tcl/packages$
thufir@dur:~/tcl/packages$ echo 'puts $tcl_pkgPath' | tclsh
/usr/local/lib/tcltk /usr/local/share/tcltk /usr/lib/tcltk/x86_64-linux-gnu /usr/lib/tcltk /usr/share/tcltk /usr/lib/tcltk/tcl8.6 /usr/lib
thufir@dur:~/tcl/packages$
代码:
thufir@dur:~/tcl/packages$
thufir@dur:~/tcl/packages$ ll
total 16
drwxrwxr-x 2 thufir thufir 4096 May 4 02:22 ./
drwxrwxr-x 6 thufir thufir 4096 May 4 02:22 ../
-rw-rw-r-- 1 thufir thufir 215 May 4 02:21 foo.tcl
-rw-rw-r-- 1 thufir thufir 1207 May 4 02:20 tutstack.tcl
thufir@dur:~/tcl/packages$
thufir@dur:~/tcl/packages$ cat foo.tcl
package require tutstack 1.0
set stack [tutstack::create]
foreach num {1 2 3 4 5} { tutstack::push $stack $num }
while { ![tutstack::empty $stack] } {
puts "[tutstack::pop $stack]"
}
tutstack::destroy $stack
thufir@dur:~/tcl/packages$
thufir@dur:~/tcl/packages$ cat tutstack.tcl
# Register the package
package provide tutstack 1.0
package require Tcl 8.5
# Create the namespace
namespace eval ::tutstack {
# Export commands
namespace export create destroy push pop peek empty
# Set up state
variable stack
variable id 0
}
# Create a new stack
proc ::tutstack::create {} {
variable stack
variable id
set token "stack[incr id]"
set stack($token) [list]
return $token
}
# Destroy a stack
proc ::tutstack::destroy {token} {
variable stack
unset stack($token)
}
# Push an element onto a stack
proc ::tutstack::push {token elem} {
variable stack
lappend stack($token) $elem
}
# Check if stack is empty
proc ::tutstack::empty {token} {
variable stack
set num [llength $stack($token)]
return [expr {$num == 0}]
}
# See what is on top of the stack without removing it
proc ::tutstack::peek {token} {
variable stack
if {[empty $token]} {
error "stack empty"
}
return [lindex $stack($token) end]
}
# Remove an element from the top of the stack
proc ::tutstack::pop {token} {
variable stack
set ret [peek $token]
set stack($token) [lrange $stack($token) 0 end-1]
return $ret
}
thufir@dur:~/tcl/packages$
thufir@dur:~/tcl/packages$ tclsh foo.tcl
can't find package tutstack 1.0
while executing
"package require tutstack 1.0"
(file "foo.tcl" line 1)
thufir@dur:~/tcl/packages$
据我所知,我需要 包裹所在位置的列表或地图。
问题是 Tcl 没有为您的包找到索引文件(应该称为 pkgIndex.tcl
)。如果您已将 weather 1.0
程序包实现为文件 weather.tcl
,那么您可能会希望在同一目录 中找到类似这样的索引文件 :
package ifneeded weather 1.0 [list source [file join $dir weather.tcl]]
上面写着“加载 weather
包的 1.0
版本,运行 这个脚本”,其中脚本在 运行 时间生成并绑定 $dir
in(这是一个变量,总是在包索引加载器 运行s package ifneeded
的上下文中定义)。
一旦存在,您需要允许 Tcl 找到索引文件。这可以通过将该目录 或其直接父目录 放在 Tcl 全局 auto_path
列表中来完成;要么在加载任何包之前在脚本中执行此操作(对于具有内部包的应用程序非常有用),要么您也可以通过设置 TCLLIBPATH
环境变量从 Tcl 外部初始化它。请注意,该变量的值是目录的 Tcl 列表,而不是像 env(PATH)
这样的系统路径。如果您在目录名称中有反斜杠或 space,或者如果您希望列表中有多个元素,这很重要。幸运的是,在添加单个目录作为环境变量的情况下,通常可以避免所有这些问题,即使在 Windows 上,通过使用 /
而不是 \
并遵循常规安装练习而不是在名字中加入 space。在应用程序启动期间添加路径时更容易:您只需使用 lappend
,也许像这样(在您的主脚本的早期):
lappend auto_path [file join [file dirname [info script]] my_app_pacakges]
# If the script is in foo/bar.tcl then packages are in or below foo/my_app_packages
运行结果:
thufir@dur:~/tcl/foo$
thufir@dur:~/tcl/foo$ tree
.
├── api
│ ├── pkgIndex.tcl
│ └── tutstack.tcl
└── main.tcl
1 directory, 3 files
thufir@dur:~/tcl/foo$
thufir@dur:~/tcl/foo$ cat main.tcl
lappend auto_path /home/thufir/tcl/foo/api
package require tutstack 1.0
set stack [tutstack::create]
foreach num {1 2 3 4 5} { tutstack::push $stack $num }
while { ![tutstack::empty $stack] } {
puts "[tutstack::pop $stack]"
}
tutstack::destroy $stack
thufir@dur:~/tcl/foo$
thufir@dur:~/tcl/foo$ cat api/pkgIndex.tcl
# Tcl package index file, version 1.1
# This file is generated by the "pkg_mkIndex" command
# and sourced either when an application starts up or
# by a "package unknown" script. It invokes the
# "package ifneeded" command to set up package-related
# information so that packages will be loaded automatically
# in response to "package require" commands. When this
# script is sourced, the variable $dir must contain the
# full path name of this file's directory.
package ifneeded tutstack 1.0 [list source [file join $dir tutstack.tcl]]
thufir@dur:~/tcl/foo$
thufir@dur:~/tcl/foo$ cat api/tutstack.tcl
# Register the package
package provide tutstack 1.0
package require Tcl 8.5
# Create the namespace
namespace eval ::tutstack {
# Export commands
namespace export create destroy push pop peek empty
# Set up state
variable stack
variable id 0
}
# Create a new stack
proc ::tutstack::create {} {
variable stack
variable id
set token "stack[incr id]"
set stack($token) [list]
return $token
}
# Destroy a stack
proc ::tutstack::destroy {token} {
variable stack
unset stack($token)
}
# Push an element onto a stack
proc ::tutstack::push {token elem} {
variable stack
lappend stack($token) $elem
}
# Check if stack is empty
proc ::tutstack::empty {token} {
variable stack
set num [llength $stack($token)]
return [expr {$num == 0}]
}
# See what is on top of the stack without removing it
proc ::tutstack::peek {token} {
variable stack
if {[empty $token]} {
error "stack empty"
}
return [lindex $stack($token) end]
}
# Remove an element from the top of the stack
proc ::tutstack::pop {token} {
variable stack
set ret [peek $token]
set stack($token) [lrange $stack($token) 0 end-1]
return $ret
}
thufir@dur:~/tcl/foo$
thufir@dur:~/tcl/foo$ tclsh main.tcl
5
4
3
2
1
thufir@dur:~/tcl/foo$
正在生成配置文件:
thufir@dur:~/tcl/foo/api$
thufir@dur:~/tcl/foo/api$ tclsh
%
%
% pkg_mkIndex . *.tcl
%
% exit
thufir@dur:~/tcl/foo/api$
感谢大家的指点,对问题的理解又加深了一点。变量:
thufir@dur:~/tcl/packages$
thufir@dur:~/tcl/packages$ echo 'puts $auto_path' | tclsh
/usr/share/tcltk/tcl8.6 /usr/share/tcltk /usr/lib /usr/local/lib/tcltk /usr/local/share/tcltk /usr/lib/tcltk/x86_64-linux-gnu /usr/lib/tcltk /usr/lib/tcltk/tcl8.6
thufir@dur:~/tcl/packages$
thufir@dur:~/tcl/packages$ echo 'puts $tcl_pkgPath' | tclsh
/usr/local/lib/tcltk /usr/local/share/tcltk /usr/lib/tcltk/x86_64-linux-gnu /usr/lib/tcltk /usr/share/tcltk /usr/lib/tcltk/tcl8.6 /usr/lib
thufir@dur:~/tcl/packages$
代码:
thufir@dur:~/tcl/packages$
thufir@dur:~/tcl/packages$ ll
total 16
drwxrwxr-x 2 thufir thufir 4096 May 4 02:22 ./
drwxrwxr-x 6 thufir thufir 4096 May 4 02:22 ../
-rw-rw-r-- 1 thufir thufir 215 May 4 02:21 foo.tcl
-rw-rw-r-- 1 thufir thufir 1207 May 4 02:20 tutstack.tcl
thufir@dur:~/tcl/packages$
thufir@dur:~/tcl/packages$ cat foo.tcl
package require tutstack 1.0
set stack [tutstack::create]
foreach num {1 2 3 4 5} { tutstack::push $stack $num }
while { ![tutstack::empty $stack] } {
puts "[tutstack::pop $stack]"
}
tutstack::destroy $stack
thufir@dur:~/tcl/packages$
thufir@dur:~/tcl/packages$ cat tutstack.tcl
# Register the package
package provide tutstack 1.0
package require Tcl 8.5
# Create the namespace
namespace eval ::tutstack {
# Export commands
namespace export create destroy push pop peek empty
# Set up state
variable stack
variable id 0
}
# Create a new stack
proc ::tutstack::create {} {
variable stack
variable id
set token "stack[incr id]"
set stack($token) [list]
return $token
}
# Destroy a stack
proc ::tutstack::destroy {token} {
variable stack
unset stack($token)
}
# Push an element onto a stack
proc ::tutstack::push {token elem} {
variable stack
lappend stack($token) $elem
}
# Check if stack is empty
proc ::tutstack::empty {token} {
variable stack
set num [llength $stack($token)]
return [expr {$num == 0}]
}
# See what is on top of the stack without removing it
proc ::tutstack::peek {token} {
variable stack
if {[empty $token]} {
error "stack empty"
}
return [lindex $stack($token) end]
}
# Remove an element from the top of the stack
proc ::tutstack::pop {token} {
variable stack
set ret [peek $token]
set stack($token) [lrange $stack($token) 0 end-1]
return $ret
}
thufir@dur:~/tcl/packages$
thufir@dur:~/tcl/packages$ tclsh foo.tcl
can't find package tutstack 1.0
while executing
"package require tutstack 1.0"
(file "foo.tcl" line 1)
thufir@dur:~/tcl/packages$
据我所知,我需要
问题是 Tcl 没有为您的包找到索引文件(应该称为 pkgIndex.tcl
)。如果您已将 weather 1.0
程序包实现为文件 weather.tcl
,那么您可能会希望在同一目录 中找到类似这样的索引文件 :
package ifneeded weather 1.0 [list source [file join $dir weather.tcl]]
上面写着“加载 weather
包的 1.0
版本,运行 这个脚本”,其中脚本在 运行 时间生成并绑定 $dir
in(这是一个变量,总是在包索引加载器 运行s package ifneeded
的上下文中定义)。
一旦存在,您需要允许 Tcl 找到索引文件。这可以通过将该目录 或其直接父目录 放在 Tcl 全局 auto_path
列表中来完成;要么在加载任何包之前在脚本中执行此操作(对于具有内部包的应用程序非常有用),要么您也可以通过设置 TCLLIBPATH
环境变量从 Tcl 外部初始化它。请注意,该变量的值是目录的 Tcl 列表,而不是像 env(PATH)
这样的系统路径。如果您在目录名称中有反斜杠或 space,或者如果您希望列表中有多个元素,这很重要。幸运的是,在添加单个目录作为环境变量的情况下,通常可以避免所有这些问题,即使在 Windows 上,通过使用 /
而不是 \
并遵循常规安装练习而不是在名字中加入 space。在应用程序启动期间添加路径时更容易:您只需使用 lappend
,也许像这样(在您的主脚本的早期):
lappend auto_path [file join [file dirname [info script]] my_app_pacakges]
# If the script is in foo/bar.tcl then packages are in or below foo/my_app_packages
运行结果:
thufir@dur:~/tcl/foo$
thufir@dur:~/tcl/foo$ tree
.
├── api
│ ├── pkgIndex.tcl
│ └── tutstack.tcl
└── main.tcl
1 directory, 3 files
thufir@dur:~/tcl/foo$
thufir@dur:~/tcl/foo$ cat main.tcl
lappend auto_path /home/thufir/tcl/foo/api
package require tutstack 1.0
set stack [tutstack::create]
foreach num {1 2 3 4 5} { tutstack::push $stack $num }
while { ![tutstack::empty $stack] } {
puts "[tutstack::pop $stack]"
}
tutstack::destroy $stack
thufir@dur:~/tcl/foo$
thufir@dur:~/tcl/foo$ cat api/pkgIndex.tcl
# Tcl package index file, version 1.1
# This file is generated by the "pkg_mkIndex" command
# and sourced either when an application starts up or
# by a "package unknown" script. It invokes the
# "package ifneeded" command to set up package-related
# information so that packages will be loaded automatically
# in response to "package require" commands. When this
# script is sourced, the variable $dir must contain the
# full path name of this file's directory.
package ifneeded tutstack 1.0 [list source [file join $dir tutstack.tcl]]
thufir@dur:~/tcl/foo$
thufir@dur:~/tcl/foo$ cat api/tutstack.tcl
# Register the package
package provide tutstack 1.0
package require Tcl 8.5
# Create the namespace
namespace eval ::tutstack {
# Export commands
namespace export create destroy push pop peek empty
# Set up state
variable stack
variable id 0
}
# Create a new stack
proc ::tutstack::create {} {
variable stack
variable id
set token "stack[incr id]"
set stack($token) [list]
return $token
}
# Destroy a stack
proc ::tutstack::destroy {token} {
variable stack
unset stack($token)
}
# Push an element onto a stack
proc ::tutstack::push {token elem} {
variable stack
lappend stack($token) $elem
}
# Check if stack is empty
proc ::tutstack::empty {token} {
variable stack
set num [llength $stack($token)]
return [expr {$num == 0}]
}
# See what is on top of the stack without removing it
proc ::tutstack::peek {token} {
variable stack
if {[empty $token]} {
error "stack empty"
}
return [lindex $stack($token) end]
}
# Remove an element from the top of the stack
proc ::tutstack::pop {token} {
variable stack
set ret [peek $token]
set stack($token) [lrange $stack($token) 0 end-1]
return $ret
}
thufir@dur:~/tcl/foo$
thufir@dur:~/tcl/foo$ tclsh main.tcl
5
4
3
2
1
thufir@dur:~/tcl/foo$
正在生成配置文件:
thufir@dur:~/tcl/foo/api$
thufir@dur:~/tcl/foo/api$ tclsh
%
%
% pkg_mkIndex . *.tcl
%
% exit
thufir@dur:~/tcl/foo/api$