How to open a file relative to imported .py file - python

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

Related

How to read a file in Python function and call that function from some other python file?

Folder structure:
MainFolder
__init__.py
FolderA
Config.json
ConfigHelper.py
testA.py
FolderB
Test.py
ConfigHelper.py file:
import json
class ConfigHelper:
def read_config(self):
fileName = "Config.json"
with open(fileName, "r") as jsonfile:
return json.load(jsonfile)
When calling ConfigHelper.read_config() function from FolderB-->Test.py file , then
Getting Error: No such file or directory: 'config.json'
But if calling it from TestA.py file, No error is coming.
Look like it is taking path relative from the calling place.
Please tell me , How I can fix it?
When you are in FolderB there is no config.json file there.
Solutions
Run your script from MainFolder and pass correct path (FolderA/config.json).
Add folders to path, see.
Change working directory to FolderB before trying to read config.json, see.
You need to provide the full path to the file. You are right that it is looking for the relative path. When you are just passing the Config.json path it is looking in your current working directory for this.
path = os.getcwd()
print("Current Directory", path)
filepath = path + "/MainFolder/FolderA/Config.json"
Gave Full Path as above to fix the problem.

Pyinstaller single exe does not work properly and apparently, there are many people having problems that go unsolved

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])

Open .txt file with python

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?

Parent folder script FileNotFoundError

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 want files ran from main python file to run from their own directory

Example:
I have my main file, main.py with this code:
import os
os.popen("start folder/subfile.py")
Then i have my other file, subfile.py with this code:
file = open("test.txt", "w")
file.close()
I want my subfile.py to create the test.txt file in its own folder, but it creates it in the main.py's folder.
So my question is, how do i make the subfile.py run from it own folder even though it's started from main.py
main.py folder : C:/users/user/Desktop
subfile.py folder: C:/users/user/Desktop/folder
In subfile.py, change the working directory (os.chdir) to the directory that contains the subfile.py file:
import os
os.chdir(os.path.dirname(__file__))
You can use subprocess instead which has that built in:
subprocess.Popen(sys.executable + ' subfile.py', cwd=os.path.dirname(__file__) + '/folder')
Try This :
import os
import inspect
your_current_folder_path = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
your_current_file_path = os.path.join(your_current_folder_path, "test.txt")
print(your_current_folder_path)
print(your_current_file_path)
with open(your_current_file_path, "w") as make_file:
make_file.write("")
print("Done.")
Another way: you can change your working directory by os.chdir("your_folder_directory") function.
os.chdir(r"C:/users/user/Desktop/folder")

Categories