1

I want to make a Tkinter program where separate users can load their data, (a dictionary) from a sub-folder within the main project directory.

My_project
|_main.py
|
|_User_data
    |
    |_ Data.py

I made a dialog box,and have the path of the file chosen, but I cannot figure out how to import the dictionary from Data.py to be used in as a variable in main.py. How can each user load their own data on each startup?

3
  • 2
    So, the file Data.py is a Python file that defines a Python dictionary with the user's data, is that correct? If so, your approach sounds not ideal to me. Probably, the json format is what you are looking for: It is a data format that stores dictionaries in text files. Python supports it natively through its json module: use json.load() to read *.json files into Python dictionaries and json.dump() to write *.json files from Python dictionaries. Commented Oct 24 at 9:57
  • 1
    I think you should look into the importlib.util documentation. Commented Oct 24 at 10:30
  • 1
    YES! Using a text file with json and converting it to a python dictionary worked! It is still early days, but huge THANK YOU Commented Oct 24 at 12:00

2 Answers 2

0

To condense the comments into an answer: As it currently stands, the question asks for a way to load a user-provided dictionary, which is provided as part of a Python file, into a running application. The following is my opinionated answer and suggestion:

In general, I think it is not a good idea to use Python files as a way to load and save user data: Python is a programming language, and Python scripts are executable, so loading arbitrary ones at runtime can have arbitrary unwanted consequences; in particular, the execution of arbitrary, potentially malicious code. See this related question on the Software Engineering Stack Exchange for a bit of a more nuanced and general discussion (it is mainly about Python code as configuration files, but to me, the main implications are the same in both contexts).

That said, as mentioned in ninadepina's comment, it is technically possible to load arbitrary python code at runtime, see e.g. this related question. The answers to the latter are a bit outdated, and the modern (i.e. Python 3.x) approach, as also mentioned by ninadepina, would be to rely on the importlib module – have a look at Bryan Oakley's answer for a concrete example. An alternative without code execution, perhaps, would also be to parse the Python file and then get the relevant values from its AST (or using one's own parsing code to extract the relevant sections), but this looks like "using a sledgehammer to crack a nut" to me.

My actual suggestion would be to use an approach that has been specifically designed for loading and saving data. Given that dictionary data is the topic here (which, I guess, means key–value pairs), the JSON format appears as a good candidate to me, because (a) it is well recognized, human-readable and widely supported across platforms and programming languages, and (b) it has built-in Python support through the json module. See e.g. this answer as to how to load JSON data from a given file path.

Sign up to request clarification or add additional context in comments.

Comments

0

If all you are doing is loading some static data and not code, putting the data in json is going to be the simplest approach. However, importing python code is also doable and gives you the ability to use the full power of python in defining your user data.

Python has a library for doing this, called importlib. You can use it to import a module by path with importlib.util.spec_from_file_location

Here's an example of a helper function to use that method:

import importlib.util
import sys


def import_module_from_path(module_name, file_path):

    spec = importlib.util.spec_from_file_location(module_name, file_path)
    if spec is None:
        raise ImportError(f"Could not find module spec for '{module_name}' at '{file_path}'")
    
    module = importlib.util.module_from_spec(spec)
    sys.modules[module_name] = module  # Add the module to sys.modules
    spec.loader.exec_module(module)
    return module

To test it out, let's assume the user's file is in /tmp/User_data/Data.py, and that it contains the following:

# Data.py
customizations = {
    "one": 1,
    "two": 2,
}

We can now import customizations like so:

# example.py
try:
    user_data = import_module_from_path("user_data", "/tmp/User_data/Data.py")
    print(f"customizations: {user_data.customizations}")

except ImportError as e:
    print(f"Error importing plugin: {e}")

When you run the code you should see output like this:

$ python example.py 
customizations: {'one': 1, 'two': 2}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.