Load file from same folder as Python 3.x script inside package - python

Opening and loading data from a file that is situated in the same folder as the currently executing Python 3.x script can be done like this:
import os
mydata_path = os.path.join(os.path.dirname(__file__), "mydata.txt")
with open(mydata_path, 'r') as file:
data = file.read()
However once the script and mydata.txt files become part of a Python package this is not as straight forward anymore. I have managed to do this using a concoction of functions from the pkg_resources module such as resource_exists(), resource_listdir(), resource_isdir() and resource_string(). I won't put my code here because it is horrible and broken (but it sort of works).
Anyhow my question is; is there no way to manage the loading of a file in the same folder as the currently executing Python script that works regardles of wether the files are in a package or not?

You can use importlib.resources.read_text in order to read a file that's located relative to a package:
from importlib.resources import read_text
data = read_text('mypkg.foo', 'mydata.txt')

Related

Running Python code from Notepad++ doesn't generate .txt files

So currently I'm practicing Python and I have this line of code:
print(f"{someList}", file=open("generatedList.txt", "w"))
When I tried to run it on Notepad++ using a run command of python "$(FULL_CURRENT_PATH)", it doesn't generates the .txt file but in the Notepad++ folder. When I tried to run exactly the same code to the IDLE it generates the .txt file on the working folder.
Why is that? Should I change something to the run command? I prefer Notepad++ as a text editor.
Btw, I'm using Python 3.8.5
So I don't know if it is okay but I think I know now how to make it save on wherever directory you want I just experimented and tried it out.
from this code :
print(f"{flippedCoins}", file=open("generatedFlips.txt", "w"))
You'll just need to add the directory where would like to save it!
print(f"{flippedCoins}", file=open("C:\The\Directory\You\Want\to\Save\it\generatedFlips.txt", "w"))
You can use the __file__ variable to retrieve the location of the script, and use that to construct an absolute path for your output file:
import os.path
SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__))
FILE_PATH = os.path.join(SCRIPT_DIR, "generatedList.txt")
...
with open(FILE_PATH, "w") as fh:
print(f"{someList}", file=fh)
If you prefer to work with local file paths, you could change the working directory to the one where you want to dump the file:
import os
os.chdir("c:/path/to/some/directory")
If you can't locate the output file when launching the script from and IDE and want to figure out what the script's working directory is, you can print it:
import os
print(os.getcwd())
You can always provide an absolute path to the file, wherever the script is executed from:
with open("c:/path/to/some/file.txt", "w") as fh:
print(f"{someList}", file=fh)

Correct way to link to a python file

I am writing a code organized in some (several) files. For the sake of organization of folders and the CMakeLists.txt, a pythonlibs folder is created during the build process, and some links to python files are created to libraries in the /build/src/XXXX/ folder.
In the python file, I add to the python path:
sys.path.insert(1,'/opt/hpc/softwares/erfe/erfe/build/pythonlibs')
import libmsym as msym
When I run the main python file, there is this one library lybmsym that fails with:
import libmsym as msym
File "/opt/hpc/softwares/erfe/erfe/build/pythonlibs/libmsym.py", line 15, in <module>
from . import _libmsym_install_location, export
ImportError: attempted relative import with no known parent package
I created a link using cmake, but I believe it does use the ln command (tried both hard and symbolic). Is there a way to prevent this behavior without changing the library itself, just another way to create this link?
Thanks.

Run all Python scripts in a folder - from Python

How can I write a Python program that runs all Python scripts in the current folder? The program should run in Linux, Windows and any other OS in which python is installed.
Here is what I tried:
import glob, importlib
for file in glob.iglob("*.py"):
importlib.import_module(file)
This returns an error: ModuleNotFoundError: No module named 'agents.py'; 'agents' is not a package
(here agents.py is one of the files in the folder; it is indeed not a package and not intended to be a package - it is just a script).
If I change the last line to:
importlib.import_module(file.replace(".py",""))
then I get no error, but also the scripts do not run.
Another attempt:
import glob, os
for file in glob.iglob("*.py"):
os.system(file)
This does not work on Windows - it tries to open each file in Notepad.
You need to specify that you are running the script through the command line. To do this you need to add python3 plus the name of the file that you are running. The following code should work
import os
import glob
for file in glob.iglob("*.py"):
os.system("python3 " + file)
If you are using a version other than python3, just change the argument from python3 to python
Maybe you can make use of the subprocess module; this question shows a few options.
Your code could look like this:
import os
import subprocess
base_path = os.getcwd()
print('base_path', base_path)
# TODO: this might need to be 'python3' in some cases
python_executable = 'python'
print('python_executable', python_executable)
py_file_list = []
for dir_path, _, file_name_list in os.walk(base_path):
for file_name in file_name_list:
if file_name.endswith('.csv'):
# add full path, not just file_name
py_file_list.append(
os.path.join(dir_path, file_name))
print('PY files that were found:')
for i, file_path in enumerate(py_file_list):
print(' {:3d} {}'.format(i, file_path))
# call script
subprocess.run([python_executable, file_path])
Does that work for you?
Note that the docs for os.system() even suggest using subprocess instead:
The subprocess module provides more powerful facilities for spawning new processes and retrieving their results; using that module is preferable to using this function.
If you have control over the content of the scripts, perhaps you might consider using a plugin technique, this would bring the problem more into the Python domain and thus makes it less platform dependent. Take a look at pyPlugin as an example.
This way you could run each "plugin" from within the original process, or using the Python::multiprocessing library you could still seamlessly use sub-processes.

Error with Reading Files

I am working through Learn Python the Hard Way but am having a problem with an exercise that reads a file: https://learnpythonthehardway.org/python3/ex15.html
I have followed this and made sure my file is in the same folder as my python file. I keep getting the error:
Traceback (most recent call last):
File "ex15.py", line 5, in <module>
txt = open(filename)
FileNotFoundError: [Errno 2] No such file or directory: 'ex15_sample.txt'
I am entering: python ex15.py ex15_sample.txt into the powershell. I tried looking up the problem I'm having but could not find anything that helped in my case. Let me know if I am doing something wrong or if I'm missing something. Thanks
You can check your current path and whether your file exists by
import os
#get the current working directory
os.getcwd()
#check whether your file exists in the current working directory
os.path.exists("./ex15.py")
try 2 things below
Check both files .py and .txt are at same location. and then execute program.
this is how i ran the code.
C:\Users\db\Desktop\Python>python ex15.py
enter File Name: ex15_sample.txt
This is stuff I typed into a file.
It is really cool stuff.
Lots and lots of fun to have in here.
If your file is at other location you need to provide absolute path for your file. as
C:\Users\db\Desktop\Python>python C:\Users\deepakb\Desktop\ex15_sample.txt
i had my txt file at desktop this time.
A brief demonstration on working directory and relative file locations..
Say we have a text file named hello.txt with the contents:
Hello World!
that is located at "C:\Users\username\Documents\python\hello.txt"
And we have a python script named script.py with the contents:
with open('hello.txt', 'r') as f:
print(f.read())
Which is located at "C:\Users\username\Documents\python\script.py"
If I just hit the windows key and type power shell and hit enter to open it, I'll see it by default gives me a prompt at my home directory: "C:\Users\username>". From here I can execute my python script by calling C:\Users\username> python C:\Users\username\Documents\python\script.py. If I do this, however, they python interpreter would have started in my home folder, and when it tries to find "hello.txt" it will only search through the folder "C:\Users\username". That's not where the file is, so we get a file not found error.
To resolve this we have a few options. Number one is to re-write our script file to include the full path of our text file: ... open("C:/Users/username/Documents/python/hello.txt", ... This way there is no searching necessary, and the script can be run from anywhere. Another option is to change the working directory of the interpreter from within the script. You can set the working directory with the os library by calling os.chdir('C:/Users/username/Documents/python'). Finally you can set the working directory with PowerShell before calling the python interpreter using the cd command:
C:\Users\username> cd .\Documents\python\
I had the same error.
It was a mistake from me naming the file as ex15_sample.txt.
When you are creating a file in notepad, the file name would be automatically .txt
so if you have created a file just rename it as ex15_sample.
or
You can also run the same program by giving python ex15.py ex15_sample.txt.txt
As you can see the file name might be ex15_sample.txt with a .txt extension.

Pydevd with virtual code or (source provider)

we´re having python source code stored in a sql database, the code is build together to a virtual python module and can be executed.
We want to debug this modules but then of course the Eclipse debugger host doesnt know where to find the source code for these modules.
Is there a way to provide pydevd with the location of the source code, even if that means to write down the files to disk?
Write it to the disk and when doing the compile pass the filename for the code (and, when you're not in debug mode, just don't write it and pass '<string>' as the filename).
See the example below:
from tempfile import mktemp
my_code = '''
a = 10
print a
'''
tmp_filename = mktemp('.py', 'temp_file_')
with open(tmp_filename, 'w') as f:
f.write(my_code)
obj = compile(my_code, tmp_filename, 'exec')
exec obj #Place breakpoint here: when stepping in it should get to the code.
You need to add module to PYTHONPATH in Eclipse project settings and import it using the standard Python import. Then PyDev debugger should find it without any problems.

Categories

Resources