Skip to content

Instantly share code, notes, and snippets.

@heyajulia
Created December 2, 2022 18:21
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save heyajulia/fc4286b125fa99fd166a50f3582f2514 to your computer and use it in GitHub Desktop.
Save heyajulia/fc4286b125fa99fd166a50f3582f2514 to your computer and use it in GitHub Desktop.

The text below is a transcript of a conversation I had with ChatGPT, a version of GPT-3 optimized for conversation. The transcript has been lightly edited for clarity.

🚨 Warning! 🚨

The parts labeled "ChatGPT" are AI-generated.

Me: Hi, my code has two bugs and I’m not sure how to fix them. If you can help me, I’ll send you the code.

ChatGPT: Of course, I'll be happy to help if I can! Before we get started, can you tell me a little bit more about the bugs you're experiencing? For example, what error messages are you seeing, or what unexpected behavior are you observing? That will help me better understand the problem and give you more accurate advice.

Me: People can pass in an unsupported module name and this will cause an ugly error message to be printed. The unsupported model names are any string that is not included in the module_names variable. Should I send the code?

ChatGPT: Yes, please go ahead and send the code, that will help me understand the issue better and give you more accurate advice. Additionally, it would be helpful if you could include the error message that you are seeing so I can see exactly what's happening.

Me: Here are the error messages:

$ ./scripts/run util
/home/vscode/.cache/pypoetry/virtualenvs/aoc2022-liJLFT7p-py3.11/bin/python: No module named src.util.__main__; 'src.util' is a package and cannot be directly executed
$ ./scripts/run bloop
/home/vscode/.cache/pypoetry/virtualenvs/aoc2022-liJLFT7p-py3.11/bin/python: No module named src.bloop

Should I send the code now?

ChatGPT: Yes, please go ahead and send the code. It will be helpful to see exactly what you have written and where the error is occurring.

Me:

#!/usr/bin/env python

import sys
import glob
import os


def main():
    if len(sys.argv) != 2:
        script_name = os.path.basename(sys.argv[0])
        module_names = "|".join(
            [os.path.basename(d) for d in glob.glob("src/*") if d != "src/util"]
        )

        sys.exit(f"Usage: {script_name} [{module_names}]")

    module_name = sys.argv[1]

    os.system(f"poetry run python -m src.{module_name}")


if __name__ == "__main__":
    main()

ChatGPT: It looks like the issue is that you are trying to run a module that does not exist, and this is causing an error. One way to fix this would be to check if the module name that the user has entered is valid before trying to run it. You can do this by checking if the module name is in the module_names list that you create earlier in the code.

Here's one way you could modify your code to check if the module name is valid before running it:

#!/usr/bin/env python

import sys
import glob
import os


def main():
    if len(sys.argv) != 2:
        script_name = os.path.basename(sys.argv[0])
        module_names = [os.path.basename(d) for d in glob.glob("src/*") if d != "src/util"]

        sys.exit(f"Usage: {script_name} [{'|'.join(module_names)}]")

    module_name = sys.argv[1]

    if module_name not in module_names:
        sys.exit(f"Error: Invalid module name '{module_name}'. Valid module names are: {'|'.join(module_names)}")

    os.system(f"poetry run python -m src.{module_name}")


if __name__ == "__main__":
    main()

This code will check if the module name that the user has entered is in the module_names list, and if not, it will print an error message and exit. This should prevent the "No module named" error from occurring.

Let me know if that helps, or if you have any other questions.

Me: Oh no! Your code is giving an error: UnboundLocalError: cannot access local variable 'module_names' where it is not associated with a value

ChatGPT: Yes, you're right, there is an error in the code that I provided. The error is occurring because the module_names variable is defined inside the if block where the length of sys.argv is checked, so it is not accessible outside of that block.

To fix this, you can move the module_names variable outside of the if block so that it is defined in the same scope as the if statement that checks if the module name is valid. Here's how you could modify the code to fix this error:

#!/usr/bin/env python

import sys
import glob
import os


def main():
    # Create the list of module names
    module_names = [os.path.basename(d) for d in glob.glob("src/*") if d != "src/util"]

    if len(sys.argv) != 2:
        script_name = os.path.basename(sys.argv[0])
        sys.exit(f"Usage: {script_name} [{'|'.join(module_names)}]")

    module_name = sys.argv[1]

    if module_name not in module_names:
        sys.exit(f"Error: Invalid module name '{module_name}'. Valid module names are: {'|'.join(module_names)}")

    os.system(f"poetry run python -m src.{module_name}")


if __name__ == "__main__":
    main()

This should fix the error you were seeing, and it should also prevent the "No module named" error from occurring when an invalid module name is entered. Let me know if that works for you, or if you have any other questions.

Me: That seems to work perfectly! Do you think I should change module_names to be a set? Is it worth it from a performance point-of-view?

ChatGPT: Whether or not you use a set to store the module_names is up to you. Sets are useful because they are optimized for fast membership tests (i.e. checking if an element is in the set), so if you are going to be checking membership in the module_names set a lot, it might make sense to use a set.

However, in this particular case, the module_names list is only used to check if the user-entered module name is in the list, and then it is used to create a string for the error message. Since these operations only happen once, it is unlikely that using a set would make much of a difference in terms of performance.

Ultimately, the decision of whether to use a set or a list is a matter of personal preference and what you think makes the most sense for your code. If you want to use a set, you can simply replace the line that creates the module_names list with the following line:

module_names = set([os.path.basename(d) for d in glob.glob("src/*") if d != "src/util"])

This will create a set instead of a list. Let me know if you have any other questions.

Me: Can I create the set from a generator expression?

ChatGPT: Yes, you can create a set from a generator expression, like this:

module_names = set(os.path.basename(d) for d in glob.glob("src/*") if d != "src/util")

This is equivalent to using a list comprehension to create the set, but it is more concise and easier to read. Generator expressions are similar to list comprehensions, but instead of creating a list, they create a generator object that can be iterated over to produce the elements of the set.

Here's how you could use a generator expression to create the module_names set and update your code:

#!/usr/bin/env python

import sys
import glob
import os


def main():
    # Create the set of module names
    module_names = set(os.path.basename(d) for d in glob.glob("src/*") if d != "src/util")

    if len(sys.argv) != 2:
        script_name = os.path.basename(sys.argv[0])
        sys.exit(f"Usage: {script_name} [{'|'.join(module_names)}]")

    module_name = sys.argv[1]

    if module_name not in module_names:
        sys.exit(f"Error: Invalid module name '{module_name}'. Valid module names are: {'|'.join(module_names)}")

    os.system(f"poetry run python -m src.{module_name}")


if __name__ == "__main__":
    main()

I hope that helps! Let me know if you have any other questions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment