Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Register
    • Login

    Relative File Path Not Recognize by Plug-in?

    Cinema 4D SDK
    2023 python
    3
    5
    748
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • B
      bentraje
      last edited by

      Hi,

      I have a plug-in directory that goes like this:

      myPlugin.pyp
      config.json
      

      In my pyp file, I have this code block

      import json
      
      json_file = r"config.json"
      with open(json_file, "r") as f:
      	data = json.load(f)
      

      but it gives me an error of FileNotFoundError:[Errno 2] No such file or directory: 'config.json

      Is there a way around this?

      ferdinandF 1 Reply Last reply Reply Quote 0
      • S
        spedler
        last edited by

        In C++ - I expect it's the same in Python - I would call GeGetPluginPath() to find the absolute path to the plugin, then append the filename to that path. This should work no matter where the user has installed your plugin.

        Steve

        1 Reply Last reply Reply Quote 1
        • ferdinandF
          ferdinand @bentraje
          last edited by ferdinand

          Hello @bentraje,

          Thank you for reaching out to us. The reason for this behavior is that you are here using a Python interpreter in a shared environment. When you launch a Python script with a standalone Python interpreter, e.g., CPython 3.11, the working directory of the interpreter is set to be the directory of the interpreted py file. This is then expressed by os.getcwd which returns that working directory:

          704df48c-6fec-4acc-95e8-f60405424558-image.png

          Python then makes all its magic relative path thing happen with this path; all relative paths are relative to it. But for a Cinema 4D plugin, the working directory is the application directory and not the plugin directory because here a shared interpreter is running.

          import os
          
          print(f"{os.getcwd() = }")
          

          f70c2a1b-3fdf-41ee-9408-1cdbb16219a1-image.png

          One must construct local paths manually in this case. The common way to do this is the __file__ attribute of a module, it will always contain the location of the module file, no matter where it is on a machine.

          import os
          
          ROOT_PATH: str = os.path.dirname(__file__)
          CONFIG_FILE_PATH: str = os.path.join(ROOT_PATH, "config.json")
          
          print (f"{__file__ = }")
          print(f"{ROOT_PATH = }")
          print(f"{CONFIG_FILE_PATH = }")
          
          __file__ = 'C:\\Users\\f_hoppe\\OneDrive - MAXON Computer GmbH\\support\\pc14379\\pc14379.pyp'
          ROOT_PATH = 'C:\\Users\\f_hoppe\\OneDrive - MAXON Computer GmbH\\support\\pc14379'
          CONFIG_FILE_PATH = 'C:\\Users\\f_hoppe\\OneDrive - MAXON Computer GmbH\\support\\pc14379\\config.json'
          

          Cheers,
          Ferdinand

          MAXON SDK Specialist
          developers.maxon.net

          1 Reply Last reply Reply Quote 2
          • B
            bentraje
            last edited by

            @spedler @ferdinand

            Thanks for the response! Just checked the documentation, can't use GeGetPluginPath(). Per documentation, it does not behave the same with as C++. So I ended up using the __file__ method.

            Works as expected. Thanks for the illustration code!

            ferdinandF 1 Reply Last reply Reply Quote 0
            • ferdinandF
              ferdinand @bentraje
              last edited by ferdinand

              Hello @bentraje,

              Yes, the Python variant of GeGetPluginPath is not that useful as it just calls the C++ implementation which will then return the Python module path because the Python module is the C++ plugin which is calling GeGetPluginPath in that case. I will make the function description a bit more clear about that and also add a little example snippet for the module attribute __file__.

              And as what I would consider a fun fact:

              The __file__ attribute of modules is one of the many things where the language Python took inspiration from C/C++. In C++, __FILE__ is the macro which refers to the source file it is referenced in. I used this for example recently in the C++ Color Management examples to load an ICC file which is located next to a source file. But since users are usually not in the habit of compiling their C++ code themselves, or if they do, then want to move the resulting binary to a different place, __FILE__ is much less useful than __file__ as C++ there is a difference between the source and the executable.

              Cheers,
              Ferdinand

              MAXON SDK Specialist
              developers.maxon.net

              1 Reply Last reply Reply Quote 1
              • First post
                Last post