0

So I have this little script that I want to run:

do_something.py

from do_something import do_it

do_it()

Now this 'do_something' package has three files in it:

do_something/__init__.py

from .things_to_do import do_it

do_something/things_to_do.py

from .the_thing import the_thing

def do_it():
    print(f"Do it with {the_thing}")

do_something/the_thing.py

the_thing = "The thing"

I can run my script with python do_something.py and I get the correct output.

Do it with The thing

Now what I need is being able to run the thing without the script, using python do_something (without the '.py' extension) as well as from the original .py script (for historical reasons).

So I created:

do_something/__main__.py

from .things_to_do import do_it

do_it()

Unfortunately, this breaks in __main__.py, line 1:

    from .things_to_do import do_it
ImportError: attempted relative import with no known parent package

If I remove the '.' in the import directive, the error now appears in line 1 of things_to_do.py...

    from .the_thing import the_thing
ImportError: attempted relative import with no known parent package

How would you fix that code so that python do_something or python do_something.py are equivalent?

Thanks a lot!

Note: I also tried to mess with sys.path with very little success...

0

1 Answer 1

1

the correct solution is to use do_something.py and run python -m do_something, and have do_something.py directory on your PYTHONPATH or current directory.

the bad solution is to create a file do_something that has no extension next to your do_something.py and have the code inside do_something run your do_something.py.

import runpy
import os
current_folder = os.path.dirname(os.path.abspath(__file__))
runpy.run_path(os.path.join(current_folder,"do_something.py"),run_name=__name__)

now this is a very bad design, and the proper way is to use python's -m arguments as in the first line of this answer, but this will just isolate the "corruption" to one file that has no logic.

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

7 Comments

Thanks a lot for quick your answer! Can you elaborate on why that would be "a very bad design"? I feel like this is very natural, and __main__.py would help...
@Primos this is no longer a python file, it's a text file, any linter/IDE won't identify it as a python file, and any test framework or package manager will fail to run it, github will require extra modifications to know its a code file and it's just bad all around ... this is not how python is made to work, and would be called "not pythonic" by any python coder.
@Primos also if this helped you be sure to mark it as the correct answer and upvoting is up to you.
Thanks again @ahmed-ask. I really do understand that running one script from another wouldn't be a good idea. That is not what I plan to do. I'm just trying to avoid the -m option, and simply allow not to have to add the .py extension. In my opinion, that would be elegant, and __main__.py looks like the feature I need. Anyway... if it's not possible, it is not. As for the GitHub argument, I really don't get it. Everything is Python in my initial question, no confusion there. Thanks anyway.
@Primos, it only makes sense to you, but anyone else working on the project or using it with any experience in python will complain, you can have do_something as a shell script and let it do python -m do_something if you want to omit the .py and -m in the shell.
|

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.