0

I want to import a .png file with

import matplotlib.pyplot as plt
O = plt.imread('C:/Users/myusername/Downloads/Mathe/Picture.png')

I have the absolute Path, but it still gives me the Error:

[Errno 2] No such file or directory

Any suggestions for a python newbie?

At first I used relative Path, switched to absolute Path.

sophros
  • 14,672
  • 11
  • 46
  • 75
Markus
  • 125
  • 1
  • 6
  • Have you verified the image is in the path specified using the command line tool? – pragmaticprog Oct 14 '19 at 20:39
  • 1
    copy and paste that into an windows explorer address bar and see what happens – SuperStew Oct 14 '19 at 20:39
  • @Markus, Are you sure the "/" should not be "\" ? Could you please check? – akaur Oct 14 '19 at 20:41
  • Check the image is there first. If it is, check you app has OS permissions to read that file. Finally, it'd be worth verifying the method you are calling works with forward slashes `/`. On Windows, it's more usual to use backward slashes, which need escaping, so you'd have `C:\\Users\\myusername\\Downloads\\Mathe\\Picture.png`. That being said, forward slashes are supported by Windows too, and so the method *should* also support it, but you never know what they're doing under the hood unless you look. – benmccallum Oct 14 '19 at 20:53

2 Answers2

1

As stated by the previous answer, you shouldn't hard-code paths and in general, to access the home directory of the current user, you can use os.path.expanduser("~") and with some input control, your program becomes:

import os
import matplotlib.pyplot as plt

picture_path = os.path.join(os.path.expanduser("~"), "Downloads", "Mathe",
                            "Picture.png")
if os.path.isfile(picture_path):
    im = plt.imread(picture_path)

You can check the full documentation of os.path here.

As Eryk Sun noted in the comments, while in this case it works, In Windows, it's actually not advised to use os.path.expanduser("~") (i.e. the user's profile directory in most cases) because most of the special paths (i.e. known folders) are relocatable in the shell. Use the API to query the Windows shell for the path of a known folder (e.g. FOLDERID_Downloads). There is an example to do so using PyWin32 and if it's not possible to use Pywin32, the answer links to another method using ctypes.

Finally, you may have something like that

import matplotlib.pyplot as plt
import os

import pythoncom
from win32com.shell import shell

kf_mgr = None
def get_known_folder(folder_id):
    global kf_mgr
    if kf_mgr is None:
        kf_mgr = pythoncom.CoCreateInstance(shell.CLSID_KnownFolderManager,None,
                                            pythoncom.CLSCTX_INPROC_SERVER,
                                            shell.IID_IKnownFolderManager)

    return kf_mgr.GetFolder(folder_id).GetPath()

picture_path = os.path.join(get_known_folder(shell.FOLDERID_Downloads), "Mathe", 
                            "Picture.png")
    if os.path.isfile(picture_path):
      im = plt.imread(picture_path)
RMPR
  • 3,368
  • 4
  • 19
  • 31
  • I saw on your (very detailed) answer that it's for the actual data of the program, here I think he's trying to access some random files on the disk. – RMPR Oct 15 '19 at 19:11
  • 1
    A user's "Downloads" directory is a relocatable known folder. This is used with roaming profiles to minimize how much has to be downloaded and synchronized when a user logs on. However, this doesn't even have to be managed by organization policy. A user can manually open the properties dialog for a known folder and change its location. In the GUI, the shell will present the folder as if it's in the profile, but it's not actually there. It's just a high-level abstraction. At the command line or API level, it won't be present in the default location unless a junction is also created. – Eryk Sun Oct 15 '19 at 19:33
0

If you're using Windows, that path may cause issues because of the direction of the slashes. Check out this article. You shouldn't hardcode paths because regardless of which direction of slash you use, it can break on other operating systems.

It should work with something like this:

import os
import matplotlib.pyplot as plt

picture_path = os.path.join("C:", "Users", "myusername", "Downloads", "Mathe", "Picture.png")
im = plt.imread(picture_path)
nheise
  • 311
  • 1
  • 8
  • Windows/DOS has always supported both slashes, and still does. – ekhumoro Oct 14 '19 at 21:04
  • From the article I linked: "Technically this code will still work on Windows because Python has a hack where it will recognize either kind of slash when you call open() on Windows. But even still, you shouldn’t depend on that. Not all Python libraries will work if you use wrong kind of slash on the wrong operating system — especially if they interface with external programs or libraries." Isn't it always safer to use ```os.path.join``` or ```pathlib```? – nheise Oct 15 '19 at 07:59
  • 1
    In your answer, you say: "If you're using Windows, that path **won't work** because of the direction of the slashes". This is clearly wrong (as also stated in the article you quoted from). The fact that there may be bugs in some third-party libraries is irrelevant. – ekhumoro Oct 15 '19 at 10:37
  • Corrected to be a bit more precise :) – nheise Oct 15 '19 at 10:44
  • 1
    @nicholashz, Python `open` has nothing to do with the recognition of "/" as a path separator in Windows. We pass the path directly to C `_wopen`, which passes it to Windows `CreateFileW`. Slash is a reserved character in the file-system namespace. The system runtime library translates slash to backslash when normalizing a DOS path to a NT path for use with the native API (e.g. WINAPI `CreateFileW` -> native `NtCreateFile`). In the Windows filesystem API, only a non-normalized path *must* use backslash, i.e. a path that starts with exactly "\\?\". – Eryk Sun Oct 15 '19 at 16:33