Glad to hear everyone worked it out! Here's a bit more detail about what was happening for you, @Leahstars -- basically an expanded version of what @dull was saying.
When you specify a path like static/something.png
, you're saying "the file called something.png
inside the static
subdirectory of the current working directory". Every process has a working directory; by default for a website's code, it's /home/yourusername
, but if (for example) you're running code in Bash, it will be the directory you used the cd
command to navigate to. A lot of people find this confusing when they're starting out, because it's reasonable to assume that the working directory is the one containing the script that contains the code that is currently running -- but that assumption is generally wrong, unless you happen to be running the code from a Bash console where you've already used cd
to navigate to the directory. This is all made more confusing by the fact that when you're starting out, very frequently you do use cd
to navigate to a script, then run something like python myscript.py
, so things work -- but that's really just by chance.
It's normally good practice to write your code so that it's independent of what the current working directory is. This is because the working directory can be changed by other code, and if (say) some library that you import messes around with the working directory when you're not expecting it, your code will break if you make assumptions about what it is.
The easiest (but not the best) way to avoid problems like that is to always use absolute paths. Absolute paths start with "/", and specify the location of a file from the top of the filesystem hierarchy. For example, if your code is in the mysite
subdirectory of your home directory, then the absolute path to that is /home/yourusername/mysite
, if it there is a directory called static
inside that directory, you can find that at /home/yourusername/mysite
. So if you specify a path that starts with a "/" and goes all the way down to the location of your file, it will work. (And if you put a "/" at the start of a path that isn't an absolute one from the top of the filesystem hierarch, like in your original code, it won't find the file because it will be looking in the wrong place.)
Using absolute paths is easy to do, but hard to maintain, because of course it means that if you ever change the location of your files, everything will break until you've fixed all of your paths. You could have some constant string somewhere and then add that to the start of your files, but that still won't be easy to maintain if you're sometimes running your code on your own machine, and sometimes on PythonAnywhere.
So a slightly more complicated, but generally much more maintainable way to do it is to write some code to make the path resolution actually work the way that people naturally assume it would -- that is, to have paths that are relative to the script where the code is
In Python, there is a magic variable called __file__
. It's always set (unless you're typing code into an interactive console), and it always reflects the location of the file that's currently running -- that is, inside /home/yourusername/something/somethingelse/myscript.py
, it will be set to the string "/home/yourusername/something/somethingelse/myscript.py", and inside /home/yourusername/mysite/myscripts/myscript2.py
if will be set to "/home/yourusername/mysite/myscripts/myscript2.py"
Given that, you can work out the location of a file relative to the currently running script by using the functions in os.path
. Here's how to get the full path to the directory containing the code in which it appears:
my_dir = os.path.dirname(os.path.abspath(__file__))
The os.path.abspath
is there to avoid some nasty complications that I'm not going to explain here because this post is already much too long :-) The os.path.dirname
, like you would expect, takes the path to a file, and returns the path to the directory containing it.
Once you have your dirname, you can use os.path.join
to create paths to files relative to it. For example, if you want to say "go up one directory, then down into a directory called static
, then find the file myimage.png
", you would have this:
my_image_file = os.path.join(my_dir, "..", "static", "myimage.png")