From syntax import frustration

Hi all. I’m looking forward to this forum.

I’m in ex45, and in the middle of trying to make my own text-based game. In the game there are soldiers. The soldiers, unsurprisingly, hold weapons. My file structure is:

soldiers/
    base_sol
    cavalry
    archer
    weapons/
        base_weap
        lance
        longbow

just to give an idea. In truth, there are more kinds of soldiers and many, many more kinds of weapons. I need to have these weapons imported into the soldiers who are using them. I have them all loaded in the base template. Writing imports for each one of the weapons is a tedious task. However, finding how to import all the modules in one directory (all the classes stored in the files in one folder) has proven even more time consuming.

Here is a link to a Stack Overflow question that asks just this. The accepted answer says to stick __all__ = ['string', 'of', 'all', 'files', 'that_you_are_going_to_need_to_import] in the __init__.py in that directory. For this, I get SyntaxError: invalid syntax, with the carrot pointing to the second underscore after ‘all’. I see a ‘commentator’ (one who comments?) there also had a problem, but he seemed able to solve it, linking to something I could not comprehend the relevance of. (Problem!)

The questions are old, so I thought maybe all got revised or something, but it’s still boldly sitting here in the Python 3.6 documentation. I have searched the error message, getting nowhere. There are other options in the SO question, all of them involving a bunch of things I don’t know how to do. (What is glob?) This is the longhand version of saying I need help/guidance.

Thanks

I would like to add that I created a spike, like Zed suggested to me in the Gitter forum for a different problem, basically an experiment skeleton project to, well, experiment on to figure out a problem. There I’m not getting the SyntaxError, though it still doesn’t work. Exactly how it doesn’t work depends on how I’m structuring the project, I’ve gotten ModuleNotFoundError, AttributeError and NameError.

If I try hard enough, maybe I’ll find a way to give myself a ZeroDivisionError too.

Yipee! I got blown apart on Stack Overflow for asking this! Enjoy the fun here.

Ach, they took out more than ten of the comments. It’s less fun now. (Though it has the added bonus of making me look worse, because all of my self-defense got edited out (for some reason…), except for one piece.)

1 Like

If I’m reading this right your problem is that you have a lot of little classes in a lot of python modules, and it’s tedious to do this:

from soldiers.cavalry import NineLegHorseCavalry
from soldiers.cavalry import FourLegHorseCavalry

And so on? This might be the case that, if I had you code I could just go in and propose both a way to do this and a way to restructure so you don’t have to do this, so if my recommended solutions are off then it’s time to show the code.

First thing, I’m going to bet that you are using classes to indicate things that should be attributes. For example, cavalry and archers are just soldiers who have horses and/or bows. I would look at generalizing soldiers into one class, and then have the things they use be classes. Let’s take bows vs. swords. If you have Archer, and Soldier, they’re basically the same person just holding two different weapons. Why not just have Soldier, and then two Weapon types: Bow and Sword. When you tell a Soldier to hit, it just uses it’s Weapon, but that is a subclass that does whatever it does. Same with Horse vs. Cart vs. Walking.

Then you just import Soldiers and “wire them up” rather than importing every possible subclass of soldier you could ever think of. Another way to put this is: An attribute is superior to a subclass. If you subclass something just so it can have a different attribute (“This guy has blue eyes but that guy has green eyes and this woman has black eyes.”) then you’ll run into this trouble.

Then, the next thing is, I wouldn’t try to find tricky ways to automagically import a bunch of things. If you’re doing this then there’s a good chance you’ve either done something wrong and need to rethink it, or you just have to bite the bullet and go for it. One thing is, rather than importing every single class, I’d do this:

from soldier import cavalry, archer
from soldier.weapon import longbow, lance

Then your code is doing longbow.LongBow everywhere. But, this bring up the final thing:

Why so many modules? If you have a LongBow class inside a longbow module then that’s too much cutting this up. It’s fine to just put the LongBow class inside a weapons.py file and be done with it. If your problem with doing this is that the weapons.py file is huge then I’m going to guess you need to pull some code that’s common between LongBow and Lance out into their base class and they both use it. Basically, if you’re doing a subclass of GenericWeapon into LongBow and Lance, then they should all be in weapons.py so that they can be used and worked with easily.

1 Like

I have been working on this problem for over six hours, and I feel like this is the first normal and comprehensible solution I’ve seen or heard.

(To be fair, the SO answers may have been normal, but I certainly couldn’t figure them out, sort of like the documentation I’d already read that they attempted to throw at me. I got in touch with my one friend who knows Python, and he really worked a bunch with me, and we fixed a bunch of small problems, but not the overall structure, just playing whac-a-bug, though I do appreciate all his help.)

Thanks

1 Like

Well keep in mind that SO posters are motivated to crank out short answers that are new so they can get those points. Most don’t really care if you learn anything deeper than what’s necessary.

I also realized one more thing I think you’re doing. Do you write all this code and then try to get it working? Or, do you do what I recommend in the videos and the book where you write a little, get it working, write a little more, get it working, etc.? I’m thinking if you cranked out this huge structure but can’t import it, then you probably didn’t build it incrementally. If you’d built it incrementally then you’d have hit this problem at one class in a module and would have had to solve it. It’s better to do this incrementally, and tests really help to make incremental work easier.

I’m going to end up tearing up a bunch of code implementing your suggestion, which I’ve already put a couple of hours of work into. I suppose that is proof that it was too big.

(This comes after the whole ‘burn down the house’ conversation on Gitter, by the way, where I threw out my first try entirely. I suppose I’ll learn to downsize at some point.)

I’m not interested in beating a dead horse, but I’ve been reworking the code. As far as I can tell, if I start to rewire all the ‘soldiers’ through one master class, I’ll need to be feeding their ‘stats’ anytime a new player/foe/ally is instantiated. (Right now I’m giving them number value for attack, defense, speed and vitality.) I’m worried about the tedium. As of now, I use randint to get some variance inside each subclass of soldier I made, but each one has their own range. Since there were such a wide range of weapons used by standard infantrymen, I put in a cute system for randomly generating three weapons for general infantry. All of this is making me wonder if this is really green eyes and brown eyes, or if maybe I really do need a subclass system.

I made gists of the cavalryman and a general infantryman, just to give a clearer picture.

Alright, you’re getting closer to a solution that’s more optimal. Take a look at this Cavalryman and Infantryman you have here. See in your init and your other parts that really this is just data? In theory you don’t need to have any Python code for this. Your entire world can be just a big JSON file that loads all different kinds of soldiers, all configured based on what the data says. That’s solve your problem of tedium because, you could then just write a python script that generated all the .json for your world.

We’re on it.

(With a plug for DuckDuckGo)

Hi, it looks like Zed gave you the best answer. It sounds like you are likely using too many classes, with little variation between the classes.

In my experience, Python’s import mechanics isn’t for the faint hearted. It’s quite a complex beast, and it’s not generally well explained.

I looked at the Gist but I couldn’t work out what you were trying to achieve. If you posted the entire module, then we could have a look and suggest an improvement.

I’d made a really simple example of the classes, so that arbitrary soldiers can fight one another with a weapon of choice. I put it as a gist: https://gist.github.com/ddmee/273c57f17ed365e994726c753c4932e8

Hey. Been a while since I was here. Thanks for the offer, you can see my rather nonexistent attempt at GitHub.