Python FileNotFoundError when using open() - python

I'm using with open('myFile', 'rb') as file: to read a file. When running the program with python myProgram.py everything works fine. But as soon I try to run it without cd-ing into the directory of myProgram.py and use an absolute path instead (like python /home/myName/myCode/myProgram.py I always get this error message: FileNotFoundError: [Errno 2] No such file or directory.
So why does open() behave differently depending on how the Python program is started? And is there a way to make things work even if starting with an absolute path?
I've already tried open('/home/myName/myCode/myfile', 'rb') but without success...

So why does open() behave differently depending on how the Python program is started? And is there a way to make things work even if starting with an absolute path?
Because that is standard behavior. Not just for Python, but for all applications (at least all that I know of). A relative path (like 'myfile') is assumed to be in the current directory. That path will change depending on what directory you are sitting in when you launch the script from a shell. If you don't give an absolute path, how would Python know which file to use in a directory structure like this?
root
|-- dir1
| `-- myFile
`-- dir2
`-- myFile
You were on the right track with open('/home/myName/myCode/myfile', 'rb').

Let's say you run pwd and it returns /home/myName. If you then run /home/myName/code/myProgram.py, the working directory of your program is not /home/myName/code; it's /home/myName. The working directory of a process in inherited from the parent process, not set based on where the script is located.

Related

How to get executable filename from bundled python

Just as reference imagine the following project structure:
/testapp
| __main__.py
| firstclass.py
| secondclass.py
To make installation and deploy easier I decided to bundle these files using the trick below:
zip the .py files
echo '#!/usr/bin/env python3' | cat - testapp.zip > testapp
The issue now is that "firstclass.py" needs the abspath of "testapp".
If I run this bundled testapp and asks for __file__ it returns the script path, for example the path for "firstclass.py" not "testapp" (the executable).
I also tried using sys.executable, it returns the path for "/usr/bin/python3".
Is there an easy way to get the abspath of "testapp"?
I only care for linux environments.
Also the whole point of this is due to the fact that I cannot rely on the name of "testapp", final installer can change that name and I need a reference to it.
Thanks.

How to create subdirectories while saving Python files on Mac?

I'm learning Python using a book that uses Window's based examples and they use these as examples (the comments are the filenames):
# dir1\__init__.py
print('dir1 init')
x = 1
# dir1\dir2\__init__.py
print('dir1 init')
y = 2
# dir1\dir2\mod.py
print('in mod.py')
z = 3
Now using IDLE, it attempts to import the files using:
import dir1.dir2.mod
Which will display:
dir1 init
dir2 init
in mod.py
When I attempt to do this on IDLE on my Mac it comes up with an error saying there is no module named dir1.
The point of the exercise is to package imports but I don't if I'm formatting the files incorrectly or importing incorrectly.
I think the files are not in the same directory from where the IDLE is running or looking at.
Try to see where the IDLE is on your Mac, complete path. Once find that out may be try putting the files in the same place so that python can see those files.
As an experiment, I'd suggest, writing your scripts in an editor like VS Code. cd into the directory where you have saved the script. Run the script by python yourfilename.py and see what it says then. Personally, I have never used the IDLE but I have come across python not being able to find the file.
I'm not sure what exactly you are asking, but your file structure should look like this in Finder:
which is:
dir1
|-- __init__.py
|-- dir2
|-- __init__.py
|-- mod.py
And you need to make sure that your working directory in IDLE is the directory where dir1 is located. I don't think you can change that in IDLE, but you could do this to make it work:
>>> import sys
>>> sys.path.insert(0,'/path/to/directory/where/dir1/is/stored')

Get the directory of where my script is stored

I am writing a Python script that has to execute a shell script. In my GIT repo I have plans to commit both (Python program + Shell script) in same directory in my repo.
My issue is that when someone pulls out my code and wants to run my Python script from any relative / absolute location - I need to refer the shell script in the directory where my Python script resided.
I am not sure which one I should make use of
os.path.dirname(os.path.realpath(__file__))
OR
os.path.abspath(os.path.dirname(__file__))
OR
os.path.dirname(os.path.abspath(__file__))
If I run my python script in same directory it prints same values - even if I execute from a separate directory and run my script as mentioned below I still get same values:
python ./test/test1/1.py
/x/home02/myhome/test/test1
If it so which one I should actually make use of? What is the difference in between each of them?
========== Updated =========
I created a symbolic link to my code like as mentioned below:
cd
ln -s /x/home02/myhome/test/test1/1.py 2.py
Now when I re-run my code as mentioned below -
cd
python 2.py
cd test
python ../2.py
I get the below output
/x/home02/myhome/test/test1
/x/home02/myhome
/x/home02/myhome
So I think the below one is the correct one as I am always getting the expected output:
os.path.dirname(os.path.realpath(__file__))
Well first you want the directory, so let's use os.path.dirname(...)
And os.path.abspath(__file__) should get you the path of the script, the difference between this and os.path.realpath() is the latter eliminates symbolic links, so not sure if you want that
So I'd use os.path.dirname(os.path.abspath(__file__))
The difference between os.path.realpath and os.path.abspath is the former eliminates symbolic links whereas the latter be the absolute path of a symbolic link.
In this case, the order of os.path.dirname and abspath or realpath shouldn't matter -- It would only matter if the file you passed in didn't have a directory portion.
You should use absolute path with directory name of pathname, like this:
import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
Find the common pathname manipulations (os.path) documentation to find the difference between the usage here: https://docs.python.org/3/library/os.path.html

Python: is the current directory automatically included in path?

Python 3.4: From reading some other SO questions it seems that if a moduleName.py file is outside of your current directory, if you want to import it you must add it to the path with sys.path.insert(0, '/path/to/application/app/folder'), otherwise an import moduelName statement results in this error:
ImportError: No module named moduleName
Does this imply that python automatically adds all other .py files in the same directory to the path? What's going on underneath the surface that allows you to import local files without appending the Python's path? And what does an __init__.py file do under the surface?
Python adds the directory where the initial script resides as first item to sys.path:
As initialized upon program startup, the first item of this list, path[0], is the directory containing the script that was used to invoke the Python interpreter. If the script directory is not available (e.g. if the interpreter is invoked interactively or if the script is read from standard input), path[0] is the empty string, which directs Python to search modules in the current directory first. Notice that the script directory is inserted before the entries inserted as a result of PYTHONPATH.
So what goes on underneath the surface is that Python appends (or rather, prepends) the 'local' directory to sys.path for you.
This simply means that the directory the script lives in is the first port of call when searching for a module.
__init__.py has nothing to do with all this. __init__.py is needed to make a directory a (regular) package; any such directory that is found on the Python module search path is treated as a module.
I have faced same problem when running python script from Intellij Idea.
There is a script in a
C:\Users\user\IdeaProjects\Meshtastic-python\meshtastic
It uses
from meshtastic import portnums_pb2, channel_pb2, config_pb2
and fails.
I have realized that it looks for
C:\Users\user\IdeaProjects\Meshtastic-python\meshtastic\meshtastic
and changed working directory of this script in Run Configuration from
C:\Users\user\IdeaProjects\Meshtastic-python\meshtastic
to
C:\Users\user\IdeaProjects\Meshtastic-python
so it can find this module UNDERNEATH workdir during execution
C:\Users\user\IdeaProjects\Meshtastic-python\meshtastic

Python: How do I call a script in a parent directory's subdirectory?

I'm trying to open a Python script from the Python command line. There's a bug in Python that makes adding Python to my environmental variable's path ineffective. So, I have to run Python command line from the Python directory.
My script is at c:/mydir/myfile.py
How do I open it from c:/python27/python.exe; >>?
access your parent directory by
import sys
sys.path.append("..")
then you access a subdirectory by placing a __init__.py in subdirectory and writing something in it like
__all__ = ['myfile']
then you can import myfile
Or you just want to run it. In that case you can use an absolute path. eg. python c:\mydir\myfile.py

Categories