I have strange behavior of the below code.
When I run this code from PyCharm level it works properly and return this window (including gif with Python logo!):
Window with Python logo
When I run the same python code but with using .bat and .vbs files. It will give me such error:
Error
One more thing... ".vbs" file is automatically started when windows (operating system) is turn on. ".vbs" file opening ".bat" file and ".bat" file opening ".py" file.
Do you know why python code is no able to find ".gif" when it is starting with windows operating system.
Here is code:
import tkinter as tk
class KeypadTest():
def __init__(self, master):
self.master = master
self.time_display = tk.IntVar()
global logo
logo = tk.PhotoImage(file="indeks_gif.gif")
tk.Label(self.master, height=10, width=10 , textvariable=self.time_display,bg="red").pack(side="right")
Info = """INFO"""
tk.Label(self.master,compound = tk.CENTER,image=logo,text=Info).pack()
master = tk.Tk()
KT = KeypadTest(master)
master.mainloop()
The program can't find the file. I suspect this is because you are not running the Python program from the directory where the gif file is located.
This can be adressed by supplying the full path to the image or by running the bat file from that directory regardless of where the bat file is located. I haven't tried with vbs file but I think the problem is the same.
You can experiment by including in your program a line which prints out the working directory when it starts.
import os
print(os.getcwd())
Related
I am new to python and have been messing with Tkinter and PyInstaller.
When I package my script using;
pyinstaller --onefile --noconsole window.py
and try to open it I get this error;
Traceback (most recent call last):
File "window.py", line 10, in <module>
File "tkinter\__init__.py", line 4093, in __init__
File "tkinter\__init__.py", line 4038, in __init__
_tkinter.TclError: couldn't open "orange.png": no such file or directory
Maybe I am missing something,
Here is my code;
import tkinter as tk
from tkinter import PhotoImage
casement = tk.Tk() # Window
casement.title('Squeeze') # Window Title
casement.geometry('800x800') # Window Size
casement.resizable(True, True) # Winow Resizable x, y
casement.configure(bg='white') # Window Background Color
icon=PhotoImage(file="orange.png") # Window Icon File Var
casement.iconphoto(True,icon) # Window Icon
icon = tk.PhotoImage(file='orange.png') # Button Icon
button = tk.Button(casement, image=icon, text="Open Image", compound=tk.LEFT, bg='orange') # Button
button.pack(ipadx=5, ipady=5) #Button Placement
casement.mainloop()
When you create a single-file executable with Pyinstaller it will place resources in a specially created "MEI" directory in your user temp folder (named something like "_MEI1234"). You'll need to tell Pyinstaller where to look for assets when you run the build command like so:
pyinstaller -w -F -i ".\src\assets\icons\appicon.ico" "<your filename.py here>" --add-data ".\src\assets\;assets"
This way, Pyinstaller understands that it needs to include everything from your source assets folder (src\assets\ in my example, but yours is probably different). Then, everything in your assets folder will be included in the MEI directory used by the executable.
To access these resources when your Python app runs as an exe, you can retrieve the sys._MEIPASS and prepend it to the resource path. I've put together a function that handles exactly this below!
import sys
from pathlib import Path
def fetch_resource(rsrc_path):
try:
base_path = sys._MEIPASS
except AttributeError: # running as script, return unmodified path
return rsrc_path
else: # running as exe, return MEI path
return base_path.joinpath(rsrc_path)
Then, for any external assets you can retrieve them by calling fetch_resource() on them like this
icon = PhotoImage(file=fetch_resource("my_assets/orange.png"))
Just make sure that whatever the root directory containing my_assets/orange.png is included with the build via --add-data ".\my_source_code_dir\my_assets\;my_assets" (and again, use whatever path names are appropriate to your particular project)
I have the next files inside a folder:
When I execute idsave.py from within PyCharm or from the file location inside the command line it opens this file selection window when it's supposed to do it:
But if I run the desktop shortcut I made, it does not ask me to choose a file, when running gtk-launch idsave.desktop and click the button that triggers said window I get the next error:
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib64/python3.9/tkinter/__init__.py", line 1892, in __call__
return self.func(*args)
File "/home/username/Programacion/Python/idsave/idsave.py", line 39, in open_file
dir_path = open('dir.txt', 'r')
FileNotFoundError: [Errno 2] No such file or directory: 'dir.txt'
Even though when checking if the file exists with os.listdir() it shows that the file in fact exists:
print(os.listdir(dir))
[file, file, file, 'dir.txt', 'idsave.py', file, file]
My .desktop shortcut looks like this:
[Desktop Entry]
Name=IdSave
GenericName=Idea Saver
Comment=Save Your Ideas
Exec=/home/username/Programacion/Python/idsave/idsave.py
Icon=/home/username/Programacion/Python/idsave/icon.jpg
Type=Application
Categories=Development;
The function that triggers that window is this:
def open_file():
dir_path = open('dir.txt', 'r')
root.filename = filedialog.askopenfilename(
initialdir=dir_path.readline(),
filetypes=(("All Files", "*.*"))
)
dir_path.close()
I already tried with './dir.txt' '../dir.txt' and the absolute path of the file, but the desktop entry still gives me the same error.
What am I doing wrong?
Instead of creating a desktop shortcut, you can create a bash script (.sh file) with the following code in a text editor and place it on your desktop. Name it idsave.sh.
cd "/home/username/Programacion/Python/idsave/"
python3 idsave.py
If on double-clicking the script doesn't run and opens your text editor instead, you can right click on idsave.sh and click on Properties. Then click on the Permissions tab and check Allow executing file as program (or something similar). Then click on OK.
Now you will be able to double click on idsave.sh and your Python program will launch as expected.
This will probably solve your problem.
I made a GUI for a python program that allows me to read a csv file and display the data on the GUI. The GUI works perfectly fine when I run the program through IDLE. However when I try to run the program file as it is from Windows Explorer it shows the following error.
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.1776.0_x64__qbz5n2kfra8p0\lib\tkinter\__init__.py", line 1892, in __call__
return self.func(*args)
File "C:\Python\gui1.py", line 43, in find_result
with open("RESULTS.csv") as a:
FileNotFoundError: [Errno 2] No such file or directory: 'RESULTS.csv'
This is the program code:
import tkinter as tk
import csv
root=tk.Tk()
root.title('Results')
tk.Label(root,text="Enter your Roll Number:").grid(row=1,column=1,sticky=tk.W)
tk.Label(root,text="Name:").grid(row=4,column=1,sticky=tk.W)
tk.Label(root,text="Total (Core 5 Subjects):").grid(row=5,column=1,sticky=tk.W)
tk.Label(root,text="Total (Best 5 Subjects):").grid(row=6,column=1,sticky=tk.W)
tk.Label(root,text="Percentage:").grid(row=7,column=1,sticky=tk.W)
tk.Label(root,text="Rank:").grid(row=8
,column=1,sticky=tk.W)
rno=tk.StringVar()
name_=tk.StringVar()
t1_=tk.StringVar()
t2_=tk.StringVar()
perc_=tk.StringVar()
rank_=tk.StringVar()
tk.Entry(root, textvariable=rno,justify=tk.RIGHT).grid(row=1,column=2,padx=3,pady=3)
def find_result():
tk.Label(root,textvariable=name_,justify=tk.RIGHT).grid(row=4,column=2,sticky=tk.E)
tk.Label(root,textvariable=t1_,justify=tk.RIGHT).grid(row=5,column=2,sticky=tk.E)
tk.Label(root,textvariable=t2_,justify=tk.RIGHT).grid(row=6,column=2,sticky=tk.E)
tk.Label(root,textvariable=perc_,justify=tk.RIGHT).grid(row=7,column=2,sticky=tk.E)
tk.Label(root,textvariable=rank_,justify=tk.RIGHT).grid(row=8,column=2,sticky=tk.E)
with open("RESULTS.csv") as a:
reader=csv.reader(a)
for i in reader:
if i!=[]:
if i[0]==rno.get():
name=i[1][2:]
t1=i[19]
t2=i[20]
perc=i[21]
rank=i[22]
name_.set(name)
t1_.set(t1)
t2_.set(t2)
perc_.set(perc)
rank_.set(rank)
tk.Button(root, text="Check your Result",command=find_result).grid(row=2,column=2)
root.mainloop()
Opening program with IDLE:
Opening program through Explorer:
open("RESULTS.csv") looks for that file in the current working directory, whatever that happens to be. This must be different for the two different ways you run the code. Do one of the following.
Give open an absolute path to the file instead of a relative one. If you know the location of the data file relative to the location of the program file, use __file__, which has the location of the program file, as the starting point. Note 1: that when working interactively, without running a file, __file__ does not exist. Note 2: If you do not understand 'absolute path', do a web search.
Explicitly set the current directory to the one containing the file with os.chdir(path). where path is absolute, not relative. This is more useful if opening several files in that directory.
I am making a GUI where it allows you to:
Choose a file (user would click the first button, and a file browser pops up where user can navigate to desired file)
Once selected, the "file path" of the file should be the output
Execute a batch file in the Windows command window (user would click second button, where the command window opens and uses the output from step 1)
The input in the command window would be {MyFile.bat "the file path from step 1"} for example.
Where I am now?
I am able to output the file path but I can not get the file path into the Windows command prompt window, because instead of inputting the actual file path, it inputs the name of the output, rather than the actual output.
Example:
output name = x
after step 1, x should be = C\file\path\I\want.plz
after pressing the second button: The Windows command prompt opens and the line in the window writes: MyFile.bat "x" rather than MyFile.bat "C\file\path\I\want.plz"
def Button_Open_File(self):
import tkinter as tk
from tkinter import filedialog
root = tk.Tk()
root.withdraw()
file_path = filedialog.askopenfilename()
file_dir_name = print(**file_path**)
def Button_RUN_BATCH_FILE_ON_FILE_IN_CMD(self):
import subprocess
p1 = subprocess.check_call(**r'start cmd /c MyFile.bat "file_path"'**, shell=True, cwd="c:/Users/kimk4/Documents/")
print('done')
I highlighted my problem areas with **, so as you can see, when I run this, I am able to print a file path in the Oython shell, but I am not able to get this batch file to work because instead of writing the actual path (in the window) to the file, it literally writes file_path rather than c\file\location\that\user\navigates\to.thanks in the Windows command prompt window.
I'm starting to learn Python, and I thought to create a converter from a file to another (for example, from png to avi or between other file extensions) under Windows OS for now.
I wrote a script which works fine and it completes the conversion process, but I want improve it in functionality (and then in graphics); I'm using Tkinter and I thought to load the files with the possibility to drag-and-drop them as input for the next conversion command, instead of open a folder in which to put files as "input source". I found this topic (python drag and drop explorer files to tkinter entry widget) and I used it in this way:
import sys
import os
import Tkinter
from tkdnd_wrapper import TkDND
import shlex, subprocess
from subprocess import Popen, PIPE
import glob
import shutil
root = Tkinter.Tk()
dnd = TkDND(root)
entry = Tkinter.Entry()
entry.grid()
def handle(event):
inputfilespath = event.data
event.widget.insert(0, inputfilespath)
filesdir = os.path.dirname(os.path.realpath(inputfilespath))
files = glob.iglob(os.path.join(filesdir, "*.myext"))
for inputfilespath in files:
if os.path.isfile(inputfilespath):
subprocess1 = subprocess.Popen([...conversion command given as list, not string...], shell=True)
print "\n\nConversione in corso..."
subprocess1.wait()
subprocess1.terminate()
print "\n\nProcesso terminato!"
dnd.bindtarget(entry, handle, 'text/uri-list')
root.mainloop()
The problems:
If filename has a space, there is no conversion, and process ends without even notify any error too. "inputfilespath" wants to be the generic name for all the input files which I selected, and (for what I read) I can't (?) use quotes for an environment variable hoping to include filename's whitespace...
I tried to copy different files (with the same file extension and without whitespaces into the filename) in the same folder, and if I drag-and-drop only one of them on the Entry widget, the process starts fine (and this is great!), but it continues also for all the other no-selected files with the same extension in the same folder, whereas if I drag-and-drop multiple files on the Entry widget, no conversion occurs....
It seems that filenames containing whitespace are being wrapped in braces
(Tcl list style). To get a usable filelist, you should be able to do
something like:
import Tkinter
from untested_tkdnd_wrapper import TkDND
def handle(event):
files = root.tk.splitlist(event.data)
for filename in files:
event.widget.insert('end', filename)
root = Tkinter.Tk()
lb = Tkinter.Listbox(root, width=50)
lb.pack(fill='both', expand=1)
dnd = TkDND(root)
dnd.bindtarget(lb, handle, 'text/uri-list')
root.mainloop()
Just use the tkinter file dialog, then just have it insert the files into the entry box.
Example:
filedialog = tkFileDialog.askopenfilenames(*options*)
entry.insert(END, filedialog)
Example Using StringVar:
entryVar = StringVar()
entry = Entry(textvariable=entryVar)
filedialog = tkFileDialog.askopenfilenames(*options*)
entryVar.set(filedialog
Hope this helps!