close Comments you submit will be routed for moderation. If you have an account, please log in first.
Modify

Opened 3 years ago

Closed 2 years ago

Last modified 20 months ago

#339 closed defect (fixed)

tk/tcl does not get included in the build of the executable

Reported by: anonymous Owned by: matysek
Priority: highest Milestone: PyInstaller 2.0
Component: Platform Windows Version:
Severity: normal Keywords:
Cc:

Description (last modified by htgoebel)

The executable is created but won't run unless it can find a usable tcl.init. This is the makespec being used:

python c:\Python27\pyinstaller-1.5\makespec.py --onefile --tk --windowed --console --icon=favicon.ico dpi_combo.py

Attachments (0)

Change History (18)

comment:1 follow-up: Changed 3 years ago by matysek

  • Milestone changed from PyInstaller 1.5 to PyInstaller 1.6
  • Version PyInstaller 1.4 deleted

Please provide a small code sample, which could be tested for this behaviour.

comment:2 in reply to: ↑ 1 Changed 3 years ago by anonymous

Replying to matysek:

Please provide a small code sample, which could be tested for this behaviour.

Here you go:

import re,os, urllib2, socket
from thread import *
from threading import *
from Tkinter import *

class Application(Frame):
	
	def runDownloadListThread(self):
		start_new_thread(self.downloadList,())
		
	def ClearOutput(self):
		self.listbox.delete("0.0","1000000000.1000000000")
	def printOutput(self,text):
		self.listbox.insert(END, text+"\n")
		self.listbox.yview_pickplace("end")
	def BreakDownload(self):
		start_new_thread(self.BreakDownloadThread,())
	
	def BreakDownloadThread(self):
		self.done=True
		self.printOutput("trying to cancel downloading...")
		while self.threadRun:
			pass
		self.printOutput("download cancelled...")
		
	def downloadList(self):
		self.Break["state"]=NORMAL
		self.SendBtn["state"]=DISABLED
		self.threadRun=True
		self.ClearOutput()
		self.printOutput("download started...")
		
		regexp = '<a href="(.*?)" onclick="(.*?)"><img src="(.*?)" onerror="(.*?)" width="(.*?)" id="image" alt="(.*?)"/></a>';
		
		for url in self.text.get(1.0, END).split("\n"):
			if self.done or len(url)<8:
				break
			canConnect=False
			while not canConnect:
				try:
					Input = urllib2.urlopen(url).read(100000) # czytaj max 100000 znakow
					canConnect=True
				except:
					self.printOutput("can't connect!")
					canConnect=False
					
				if self.done:
					break

			u=url.split("/")

			baseurl=u[0]+"//"+u[2]+"/"+u[3]+"/"+u[4]+"/"+u[5]+"/"+u[6]+"/"

			mangaDir=os.getcwd()+"/"
			for o in u[4:7]:
				mangaDir=mangaDir+o+"/"
				try:
					os.mkdir(mangaDir)
				except:
					self.printOutput("katalog "+mangaDir+" zostal wczesniej utworzony")


			while not self.done:
				x=0
				
				Input = urllib2.urlopen(url).read(100000)
				
				for match in re.findall(regexp, Input,re.U|re.I|re.M):
					fileurl=match[2]
					
					timeout=True
					while timeout:
						try:
							webFile = urllib2.urlopen(fileurl)
							localFile = open(mangaDir+fileurl.split('/')[-1], 'wb')
							localFile.write(webFile.read())
							timeout=False
						except:
							if self.done:
								break
							else:
								timeout=True
								self.printOutput("timeout, retry: "+url)
							
						try:
							webFile.close()
						except:
							print "nie trzeba zamykac webFile"
						try:
							localFile.close()
						except:
							print "nie trzeba zamykac localFile"
					
					self.printOutput("downloaded: "+url)
					
					if match[0]=="javascript:void(0);":
						break
					
					url=baseurl+match[0]
					
					x+=1
				if x==0:
					self.printOutput("done!")
					break
		self.printOutput("download ended...")
		self.threadRun=False
		self.SendBtn["state"]=NORMAL
		self.Break["state"]=DISABLED
		
		self.done=False
		
	def createWidgets(self):
		self.text=Text(self)
		self.text["fg"]   = "black"
		self.text["bg"]   = "white"
		self.text["width"]=100
		self.text["height"]=15
		self.text.pack()
		self.text.insert(END, 'http://www.mangafox.com/manga/one_piece/v00/c001.1/1.html\nhttp://www.mangafox.com/manga/one_piece/v00/c001.2/1.html')
		
		self.scrollbar = Scrollbar(self)
		self.scrollbar.pack(side=RIGHT, fill=Y)

		self.scrollbar["bg"]   = "#333333"

		self.listbox = Text(self)
		self.listbox.pack()
		self.listbox["width"]=100
		self.listbox["height"]=10
		self.listbox["fg"]   = "green"
		self.listbox["bg"]   = "black"
		
		self.listbox.config(yscrollcommand=self.scrollbar.set)
		self.scrollbar.config(command=self.listbox.yview)	
		
		self.Clear = Button(self)
		self.Clear["text"] = "Clear_output",
		self.Clear["fg"]   = "white"
		self.Clear["bg"]   = "black"
		self.Clear["activeforeground"]   = "yellow"
		self.Clear["activebackground"]   = "#222222"
		self.Clear["command"] = self.ClearOutput
		self.Clear.pack({"side": "left"})
		
		self.Break = Button(self)
		self.Break["text"] = "Break_download",
		self.Break["fg"]   = "white"
		self.Break["bg"]   = "black"
		self.Break["activeforeground"]   = "yellow"
		self.Break["activebackground"]   = "#222222"
		self.Break["command"] = self.BreakDownload
		self.Break.pack({"side": "left"})
		self.Break["state"]=DISABLED
		
		self.SendBtn = Button(self)
		self.SendBtn["text"] = "Download",
		self.SendBtn["fg"]   = "white"
		self.SendBtn["bg"]   = "black"
		self.SendBtn["activeforeground"]   = "yellow"
		self.SendBtn["activebackground"]   = "#222222"
		self.SendBtn["command"] = self.runDownloadListThread
		self.SendBtn.pack({"side": "left"})
	def __init__(self, master=None):
		# timeout in seconds
		timeout = 15
		socket.setdefaulttimeout(timeout)
		
		self.threadRun=False
		self.done=False
		Frame.__init__(self, master)
		self["bg"]="black"
		self.pack()
		self.createWidgets()
	def __del__(self):
		self.done=True
		while self.threadRun:
			pass
root = Tk()
root.title("Mangafox Downloader")
root.resizable(0,0)
app = Application(master=root)
app.mainloop()

After I did the building routine I had to copy whole tcl directory to the dist folder, then my *.exe file could be started without any glitches.

comment:3 Changed 3 years ago by htgoebel

Well, a *small* example would have been much sorter. Thanks anyhow.

comment:4 Changed 3 years ago by b.jaheny@…

I had the same error, but on debian squeeze, python2.7. (i've got the same with python2.6).
When i tried without the -F option, errors are the same too.
error was:

tracceback (most recent call last):
  File "<string>", line 330, in <module>
  File "<string>", line 73, in __init__
  File "GrilleGo_05/build/pyi.linux2/GrilleGo_05/outPYZ1.pyz/Tix", line 214, in __init__
  File "GrilleGo_05/build/pyi.linux2/GrilleGo_05/outPYZ1.pyz/Tkinter", line 1688, in __init__
_tkinter.TclError: Can't find a usable init.tcl in the following directories: 
    /tmp/_MEIRh9eE5/_MEI/tcl8.5 /usr/share/tcltk/tcl8.5 /home/ubuntu/trunk/build/lib/tcl8.5 /home/ubuntu/trunk/lib/tcl8.5 /home/ubuntu/trunk/build/library /home/ubuntu/trunk/library /home/ubuntu/trunk/tcl8.5.10/library /home/ubuntu/tcl8.5.10/library



This probably means that Tcl wasn't installed properly.

thank you.

B

comment:5 Changed 3 years ago by shish@…

for me, pyinstaller is looking in /usr/lib/tcl8.5, when it should be looking in /usr/share/tcltk/tcl8.5

when I hack config.dat to override this path, it works ok

using the ubuntu 11.10

comment:6 Changed 3 years ago by anonymous

for Configure.py line 128, this works for me:

            # Linux: /usr/lib with the .tcl files in /usr/lib/tcl8.3 and /usr/lib/tk8.3
            # Debian: /usr/share/tcltk/tcl8.5 / tk8.5
            # Windows: Python21/DLLs with the .tcl files in Python21/tcl/tcl8.3 and Python21/tcl/tk8.3
            #      or  D:/Programs/Tcl/bin with the .tcl files in D:/Programs/Tcl/lib/tcl8.0 and D:/Programs/Tcl/lib/tk8.0
            for attempt in ['../share/tcltk', './', '../tcl', '../lib']:
                if os.path.exists(os.path.join(tclbindir, attempt, tclnm)):
                    config['TCL_root'] = os.path.join(tclbindir, attempt, tclnm)
                    config['TK_root'] = os.path.join(tclbindir, attempt, tknm)
                    config['TCL_dirname'] = os.path.basename(config['TCL_root'])
                    config['TK_dirname'] = os.path.basename(config['TK_root'])
                    break
            break

comment:7 Changed 3 years ago by b.jaheny@…

First work for me, thank, but i'have a new error, for Tix:

_tkinter.TclError: couldn't load file "/usr/lib/libTix8.4.3.so.1"

Tix is installed on my comuter, but i got no 'libtix8.4.3.so.1'.
I got this error both on Linux and Win...

comment:8 Changed 2 years ago by htgoebel

  • Description modified (diff)

Hi b.jaheny,

since this issue is 9 month old now and was based on version 1.4, I ask you to test again using the current stable version 1.5.1.

First of all: Are us using Window or Linux?

If the error occurs there, too, please try hotfix-1.52 (https://github.com/pyinstaller/pyinstaller/zipball/hotfix-1.5.2 or https://github.com/pyinstaller/pyinstaller/tarball/hotfix-1.5.2).

When testing hotfix-1.5.2, please try the tests in e2etests/common. There is a file maketests.py for generating them. Does your problem occur there, too? If so, this would help us debugging :-)

Use ArchiveViewer to look into the the .exe. There should be a tk.pkg and a unpackTK.py at the beginning of the contained files. Look into tk.pkg to see whether it is complete.

You may also try the current development version which hopefully does not contain this error.

comment:9 Changed 2 years ago by htgoebel

  • Milestone changed from PyInstaller 2.0 to PyInstaller 1.5.2
  • Owner changed from giovannibajo to matysek
  • Severity changed from major to normal

comment:10 Changed 2 years ago by anonymous

This was still broken for me using the most current dev version grabbed via Git.

To fix this, I edited my hook-_tkinter.py file find_tk_unix function as such:

        # Linux: /usr/lib with the .tcl files in /usr/lib/tcl8.3
        #        and /usr/lib/tk8.3
        #TCL_root = os.path.join(tclbindir, 'tcl%s' % ver)
        #TK_root = os.path.join(tclbindir, 'tk%s' % ver)
        TCL_root = '/usr/share/tcltk/tcl8.5'
        TK_root = '/usr/share/tcltk/tk8.5'

This is bad because now it's hardcoded, but this fixed the build it seems.

Last edited 2 years ago by htgoebel (previous) (diff)

comment:11 Changed 2 years ago by htgoebel

@anonym: Can you please track down why tclbindir is not detected correctly?

comment:12 Changed 2 years ago by matysek

  • Milestone changed from PyInstaller 1.5.2 to PyInstaller 2.0

comment:13 Changed 2 years ago by anonymous

Still broken for me too...
I try the test, but i don't know what to do after lauching maketest.py?
I lauch all hanoi, from t1 to t16, and message was the same all the time

_tkinter.TclError: Can't find a usable init.tcl in the following directories

it's help?

comment:14 Changed 2 years ago by matysek

  • Status changed from new to assigned

comment:15 Changed 2 years ago by matysek

  • Component changed from PyInstaller to Platform Windows

comment:16 Changed 2 years ago by matysek

  • Resolution set to fixed
  • Status changed from assigned to closed

I tried provided code example with the latest development version with some tcl/tk fixes. The provided example works in onedir and onefile on 64bit win7 with python 2.7.

Closing ticket.

comment:17 follow-up: Changed 20 months ago by anonymous

Dont work for me under Linux Mint LXDE with Python 2.7.2 and latest dev version of Pyinstaller

comment:18 in reply to: ↑ 17 Changed 20 months ago by matysek

  • Priority changed from high to highest

Replying to anonymous:

Dont work for me under Linux Mint LXDE with Python 2.7.2 and latest dev version of Pyinstaller

Open a new ticket for that with paths to tcl/tk files on your distribution.

Add Comment

Modify Ticket

Action
as closed .
The resolution will be deleted. Next status will be 'reopened'.
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.