So I am confused why this simple notepad file called common.txt is not opening. I am wondering is notepad is able to be used in python.
So I am trying to say whether the file exists:
import os.path
import sys
def file_exist(common):
#test whether the file exists and open it to a data structure
if os.path.isfile(common):
return common
else:
return
def main():
common = input("enter: ")
print(file_exist(common))
if __name__ == "__main__":
main()
I did this identical code with a csv file and it seemed to work.
Output is:
enter: common.txt
None
This code worked fine for me.
I saved it as common.py, then ran it from the command line in the directory where common.py is located.
Here's the session:
C:\temp\so> python common.py
enter: common.py
common.py
The code does the following:
- Requests input
- If the input is a filename in the working directory, it prints out the filename.
- If the input is not a filename in the working directory, it outputs None.
Is there something else you want this code to do?
Related
Please note - this is NOT a duplicate of "how to open a file in the same folder as running script". I'm trying to do the opposite of it - I want to open the file in the root folder of the imported .py file, rather than the root of main.py which is the running script.
My file structure is as follows:
/email_sender/sender.py
/email_sender/template.html
main.py
Inside the main.py file I am importing the sender.py
My question is how to refer correctly to template.html from inside of the sender.py file?
The following doesn't work because it expectes the template.html to be in the root folder (where main.py is).
I know I can hardcode the path, but is it possible to refer to it in relation to sender.py?
with open('template.html', 'r') as f:
html = f.read()
import os
from sys import argv
try:
path = os.path.dirname(argv[0])
os.chdir(path)
except:
pass
You can do this in the main.py file and then to open the template will always be:
./email_sender/template.html
I found the answer
So it looks like PyInstaller actually runs in a temp directory, not your own, which explains my issue. This is an explanation for that. I guess I will keep this up incase people in the future have problems.
Original question
I am trying to use PyInstaller to create an executable of a simple python script called test.py that just creates a text file and adds numbers to it, as a test of PyInstaller. This file works correctly when run normally.
from os.path import dirname, abspath
def main():
txtfile = dirname(abspath(__file__)) + '/text.txt'
with open(txtfile, 'w') as f:
for num in range(101):
f.write(str(num) + '\n')
if __name__ == '__main__':
main()
print('script executed')
When I use:
pyinstaller test.py --onefile in the same directory as test.py it successfully creates the dist file with the binary file test inside of it.
when I cd dist and do ./test to execute the file inside dist it successfully prints out main called and script executed but it doesn't actually create the file. So, main is being called and the script is being executed, but the file isn't created at all, and I am quite confused about what I'm doing wrong..I must be getting file paths messed up? But I have specified the exact full path with os.path, so it doesn't make sense to me.
The system exit code is 0, and there are no errors raised when I call ./test
I found this that shows that PyInstaller will save to a temp file. I created this script below to check if the script is being executed directly or via PyInstaller.
import os
import sys
def create_file(path):
with open(path + '/test.txt', 'w') as f:
for num in range(101):
f.write(str(num) + '\n')
def check_using_pyinstaller():
if getattr(sys, 'frozen', False):
application_path = os.path.dirname(sys.executable)
return application_path
return os.path.dirname(os.path.abspath(__file__))
def main():
path = check_using_pyinstaller()
os.chdir(path)
create_file(path)
if __name__ == '__main__':
main()
I have two files, one bell.mp3 one main.py file, that plays back bell.mp3 via subprocess.
If I do:
pyinstaller main.py
the Dist file ends up correctly, and everything works fine, The program runs in a directory.
This is the code for my file which i call pyinst_tester.py
it creates a text file, and plays a bell.mp3 file
#
from con import * # this is just a configuration file that has g='play' in it.
import subprocess
f=open(r'/home/godzilla/Desktop/Pyinstaller testing/testfile1','w')
f.write('This has worked')
f.close()
file='/home/godzilla/Desktop/Pyinstaller testing/data/bell.mp3'
if 'play' == g:
subprocess.call(['/usr/bin/cvlc',file])
a single file is created, but if I delete the bell.mp3 file it doesn't work. In a single file isn't the bell.mp3 zipped inside the main.exe ? therefore, redundant as a separate file ?
What Is the point having a single file exe, if you need an adjacent file with all the mp3s inside?
Pyinstaller has many features and if you want to include non python files (for example mp3 files) you have to do so explicitly with the --add-binary switch.
In one file mode the executable will be unpacked into a temporary directory prior to execution of the python code.
So how to write your code to access these data files.
You might want to look at the pyinstaller documention at following sections:
https://pyinstaller.readthedocs.io/en/stable/runtime-information.html#run-time-information
https://pyinstaller.readthedocs.io/en/stable/runtime-information.html#using-sys-executable-and-sys-argv-0
I personally place all my files in a separate directory. e.g. data.
If you place the file bell.mp3 in the directory data, then you had to call pyinstaller with the option --add-binary data:data
in the one file mode the executable is extracted into a temporary directory
whose path you get get from the variable sys._MEIPASS
Your data directory will bi in the sub directory data of sys._MEIPASS
In my example I create a function, that will be able to locate the data files in normal python mode and in pyinstaller one file or one directory mode.
Just try it out it should be self explaining
simple example:
minitst.py
import os, sys
import time
is_frozen = getattr(sys, "frozen", False)
MYDIR = os.path.realpath(os.path.dirname(__file__))
def data_fname(fname):
if is_frozen:
return os.path.join(sys._MEIPASS, "data", fname)
else:
return os.path.join(MYDIR, "data", fname)
def main():
print("This application is %s frozen" %
("" if is_frozen else "not"))
print("executable =", sys.executable,
"File =", __file__,
"mydir =", MYDIR)
if is_frozen:
print("MEIPASS", sys._MEIPASS)
fname = data_fname("tst.txt")
print("will open", fname)
with open(fname) as fin:
print(fin.read())
time.sleep(5) # this shall allow to view the console e.g. on windows if clicking on the executable.
if __name__ == "__main__":
main()
now create a directory data and place a file "tst.txt"
data/tst.txt
Hello world
Now call
pyinstaller -F minitst.py --add-binary data:data -c
and call dist/minitst from a console.
The output should look like:
This application is frozen
executable = /home/gelonida/so/pyinst/dist/minitst File = minitst.py mydir = /home/gelonida/so/pyinst
MEIPASS /tmp/_MEIKGqah9
will open /tmp/_MEIKGqah9/data/tst.txt
Hello
Now concerning your code.
I compacted the code to determine the datadir a little, but it is the same logic as in the upper example
import os, sys
from con import * # this is just a configuration file that has g='play' in it.
import subprocess
basedir = getattr(sys, "_MEIPASS", os.path.realpath(os.path.dirname(__file__)))
f=open('testfile1','w')
f.write('This has worked')
f.close()
file=os.path.join(basedir, 'data/bell.mp3')
if 'play' == g:
subprocess.call(['/usr/bin/cvlc',file])
My Python app contains a subfolder called Tests which I use to run unit tests. All of my files are in the parent folder, which I will call App. The Tests folder contains, say, a test.py file. The App folder contains an app.py file and a file.txt text file.
In my test.py file, I can make my imports like this:
import sys
sys.path.append("PATH_TO_PARENT_DIR")
Say my app.py file contains the following:
class Stuff():
def do_stuff():
with open("file.txt") as f:
pass
Now if I run test.py, I get the following error:
FileNotFoundError: [Errno 2] No such file or directory: 'file.txt'
How can I fix this? Many thanks!
Assuming the file is located in the same folder as your script:
import os
parent_dir = os.path.abspath(os.path.dirname(__file__))
class Stuff():
def do_stuff():
with open(os.path.join(parent_dir, "file.txt")) as f:
pass
Explanation:
__file__ is the path to your script
os.path.dirname get's the directory in which your script sits
os.path.abspath makes that path absolute instead of relative (just in case relative paths mess your script up, it's good practice)
Then all we need to do is combine your parent_dir with the file, we do that using os.path.join.
Read the docs on os.path methods here: https://docs.python.org/3/library/os.path.html
A more explicit version of this code can be written like this, if that helps:
import os
script_path = __file__
parent_dir = os.path.dirname(script_path)
parent_dir_absolute = os.path.abspath(parent_dir)
path_to_txt = os.path.join(parent_dir_absolute, 'file.txt')
The open function looks for the file in the same folder as the script that calls the open function. So, your test.py looks in the tests folder, not the app folder. You need to add the full path to the file.
open('app_folder' + 'text.txt')
or move the test.py file in the same folder as text.txt
I have made a simple test code in python that reads from a text file, and then preforms an action if the text file contains a line "on".
My code works fine if i run the script on my hardive with the text file in the same folder. Example, (C:\Python27\my_file.txt, and C:\Python27\my_scipt.py).
However, if I try this code while my text file is located on my flashdrive and my script is still on my hardrive it won't work even though I have the correct path specified. Example, (G:\flashdrive_folder\flashdrive_file.txt, and C:\Python27\my_scipt.py).
Here is the code I have written out.
def locatedrive():
file = open("G:\flashdrive_folder\flashdrive_file.txt", "r")
flashdrive_file = file.read()
file.close()
if flashdrive_file == "on":
print "working"
else:
print"fail"
while True:
print "trying"
try:
locatedrive()
break
except:
pass
break
The backslash character does double duty. Windows uses it as a path separator, and Python uses it to introduce escape sequences.
You need to escape the backslash (using a backslash!), or use one of the other techniques below:
file = open("G:\\flashdrive_folder\\flashdrive_file.txt", "r")
or
file = open(r"G:\flashdrive_folder\flashdrive_file.txt", "r")
or
file = open("G:/flashdrive_folder/flashdrive_file.txt", "r")
cd /media/usb0
import os
path = "/media/usb0"
#!/usr/bin/python
import os
path = "/usr/tmp"
# Check current working directory.
retval = os.getcwd()
print "Current working directory %s" % retval
# Now change the directory
os.chdir( path )
# Check current working directory.
retval = os.getcwd()
print "Directory changed successfully %s" % retval
Use:
import os
os.chdir(path_to_flashdrive)