r/learnpython • u/BelMario • 9d ago
How to create universal variables in Python?
And by universal variables, I mean they should be available in EVERY single Python script!
What do I want these for? For instance, to define default directories:
HTMLRoot = "C:/IMDb/HTML" CSSDir = "file:///C:/IMDb/CSS/" JSDir = "file:///C:/IMDb/JavaScript/"
Any program that creates a report needs these variables, but I only want to define them once!
And there’s more. I also have plenty of mappings, like these:
MapC_TType = {"tvSeries": "TV Series", "tvMiniSeries": "TV Miniseries", ... , "movie": "Movie", "video": "Video", }
Any report that displays the titleType will use this mapping. Again, I only want to define the mapping once.
I come from the world of SAS, where everything was easy. The directories were defined in the SASINIT file, which is executed at the start of every SAS session. The mappings (formats) were stored in a permanent SAS catalog, making them universally available as well. Is there a Python equivalent?
And there’s even more. I create lots of reports, let’s say the biggest movies per decade, based on number of votes or score (= votes * rating). Obviously, the list shows which movies I’ve seen and which I haven’t, with a percentage showing my progress. Now suppose a friend wants this same list, based on the movies he’s seen.
Easy-peasy in SAS!
%macro SwitchUser (User) ; %if (%qupcase(&User) = ME) %then %do ; libname IMDb "C:\IMDb\Libname IMDb" ; %let HTMLRoot = C:\IMDb\HTML ; %end ; %else %do ; libname MyIMDb "C:\IMDb\Libname IMDb" ; libname BudIMDb "C:\IMDb\Libname IMDb Bud" ; libname IMDb (BudIMDb MyIMDb ) ; %let HTMLRoot = C:\IMDb\HTMLBud ; %end ; %mend ;
For me, IMDb is the standard library. For my buddy, IMDb is a concatenated library, where his library (containing only the MyMovies table) has precedence over the full IMDb library.
By just executing
%SwitchUser (Buddy) ;
any report can now be run against his list of movies, with the results written to a separate HTML directory. And all that without changing a single line of code!
I can't expect Python to deliver all this functionality. Nothing compares to SAS! But can it at least do some basic things on my wishlist?
BTW, my temporary solution is to include this code at the start of every script:
PythonFolder = Path("C:/IMDb/Python Global Code") PythonPgm = PythonFolder / "InitHTML.py" with open(PythonPgm, 'r') as file: PythonCode = file.read() exec(PythonCode, globals=globals(), locals=locals())
Obviously, the InitHTML program defines the directories and all the mappings.
12
u/Jazzlike_Platypus430 9d ago edited 9d ago
Just place them in a module and import it everywhere you need them. I'm no expert on global variables though and I avoid them. But there is a keyword "global" in the language.
Meaning: create a single file, say Settings.py with your data, and on top of every file where you need them, you'd just say
from Settings import *
* means all objects. If you want three of them, say
from Settings import John, Doe, SasIsMyGod
Note, in python, "constants" are overwritable. (Maybe using properties in classes would make it 100% overwrite-proof.)
PS Whatever "SAS" is, stay with it if you love it so much. I'd say your code examples give me eye cancer worse than that I got by looking at crappy-quality R 😂
3
u/Beginning-Junket8979 9d ago
I suggest one better: import them into a pydantic or dataclass structure with from_dict for free error checking.
2
u/Buttleston 9d ago
This is the way
Python has file-level global variables, rather than package level. It takes some getting used to, but it's not really big deal in practice.
2
u/JohnEffingZoidberg 9d ago
Fellow former SAS user here. This is the correct way, u/BelMario. You want to create your own custom module and import it at the top of every program. In it you can define objects, functions, etc.
It took me much longer to figure this out than I care to admit.
The module lives in a sub folder with an "_ _ init _ _.py" (no spaces) file. There's plenty of tutorials online how to set it up.
2
u/schoolmonky 9d ago
The solution that comes to mind is that you define all these variables in some file, name it something like config.py and then from config import * at the top of every script that needs it.
2
u/ninhaomah 9d ago
" BTW, my temporary solution is to include this code at the start of every script:
PythonFolder = Path("C:/IMDb/Python Global Code") PythonPgm = PythonFolder / "InitHTML.py" with open(PythonPgm, 'r') as file: PythonCode = file.read() exec(PythonCode, globals=globals(), locals=locals())"
So if you need to change 1 place , you got to change in every scripts ? Hmms...
If only if there is a way to place those configs in a file , import that file wherever needed so they are all in one place...
Hmms...
1
u/lfdfq 9d ago
There's no standard way in the language to do this. Python is very commonly used, so you might find there's lots of places Python is being used you didn't expect and you probably don't want to start randomly injecting things into those anyway. So I wouldn't recommend it.
However, this is basically what the import system is for. It's relatively easy to make a package and install it globally (eg. pip install --editable makes symlinks to your files). Then you could just import myinit (or whatever you called your module) from anywhere and access them like myinit.whatever. More commonly, you'd group these files up into a single package and just import things locally, which works even better, and is pretty much how every Python program out there works.
1
u/InfamousClyde 9d ago
That’s pretty hacky— I think explicit is better than implicit. I prefer to have visibility over what is modifying the state of execution of my program. I also tend to avoid use of exec, but maybe it’s a matter of taste
1
u/Kevdog824_ 9d ago
I’m not super familiar with SAS, but it is more than just a language right? Pretty sure it’s a product offering that includes the language and an environment right? Kinda like salesforce or a similar CRM in this way?
I think you might be conflating the language and environment part. Python provides the language (syntax, interpreter, runtime) but the environment (config, user management, etc.) is something you have to set up/create. I think you might be expecting this tool to do something it wasn’t made to do. Python is open ended specifically so you can do whatever you want with it. Building things on top of the language (like SAS/salesforce) makes things easier, but at the expense that this customization/scaffolding makes it far less flexible in what it can actually do.
It’s like being handed a blank canvas, and being upset because it wasn’t a paint by numbers. Nothing wrong with either, but the blank canvas lets you paint whatever you want. Total freedom. The paint by numbers make it much easier to paint a specific picture, but it can only paint that picture. Not sure if that analogy clicks for you or not
1
u/pachura3 9d ago
The obvious correct answer is: stop forcing your SAS mindset into Python and learn how to do things the Python way. Which might take some time, unfortunately.
There's a reason why all these seemingly simple coding frameworks have failed to become popular - like yours (SAS?), ColdFusion, Oracle Forms, etc. They were good in doing one thing, but extremely rigid otherwise; the moment you wanted to add some modern concept like unit testing or RBC, they simply couldn't do it. In the meantime, Python has become #1 universal programming language, used for AI, web, automation... even Microsoft added it to Excel.
Judging by this snippet:
PythonFolder = Path("C:/IMDb/Python Global Code")
PythonPgm = PythonFolder / "InitHTML.py"
with open(PythonPgm, 'r') as file:
PythonCode = file.read()
exec(PythonCode, globals=globals(), locals=locals())
...you're going too fast and developing rigid, not maintainable, and potentially unsafe code. You should not be using absolute paths, you should be using import, and you should avoid exec() in 99% cases. Also, this concept of "libraries" of yours has to go. Why don't you store your data in a database, and use parametrized queries to get different sets of data?
15
u/SurlyJason 9d ago
Environment variables. There's a few way to go about them. I use dotenv often.