How to send an argument to another file in python 3 - python

So, I have been looking at other threads on this topic but they do not use the Module version of passing the argument to the other file, if so wasn't explained clearly enough for me to understand.
I have tried just to show I'm not just asking:
#MoneyCounter.py
import Password
enter = False
Password.system(enter)
def start(check):
if check == True:
main()
elif check == False:
print("Critical Error occured")
exit()
And my other file
#Password.py
import MoneyCounter
def system(check):
if check == False:
password() #This goes to password def not mentioned in this code
elif check == True:
MoneyCounter.start(check)
The error I am getting is the Module Password has no attribute system

The error I am getting is the Module Password has no attribute system
Of course it doesn't. The definition doesn't exist by the time the line of code is executed, since execution of the first file got interrupted by the import.
Either refactor or reorder your code so that the name isn't accessed until it exists, or remove the requirement that each module has for the other.

Your problem here is circular dependency/imports.
An import statement really executes the code in the imported file; that is, all the statements are executed, everything that is defed in the imported file gets defined etc. imports get imported, too.
So what's happening is this:
you run
$ python MoneyCounter.py
Python reads MoneyCounter.py, executes its first statement: import Password
Python reads Password.py, and executes its first statement: import MoneyCounter.py
Python reads MoneyCounter.py, this time it encounters import Password, but already has password in its list of known names; so it continues to
enter=False; Password.system(enter).
Now, Python already has a Password in its name lookup dictionary: the half-imported Password. In that, def system… hasn't happened yet, so Password.system is still unknown.
Generally, your architecture is questionable. Why would the Password "utility" module call into your "master" business logic? Better not do that, but write code that actually checks the return value of Password.system and acts based on that in your MoneyCounter.py.

On the assumption that MoneyCounter.py is the entry point (the name you run from the command-line), then I suggest you replace this:
enter = False
Password.system(enter)
with this:
if __name__ == "__main__":
enter = False
Password.system(enter)
That will only be executed from the entry-point (which is called __main__) and not when it is imported. However, you should reconsider your design.
Edit:
name is a reference to the text name of the current module. With modules that are explicitly imported the name is taken from the filename, but the entry-point (where the program starts) is always called __main__. So we can always test if we are running as an imported module or as an entry-point.
This test is extremely common in python. This way we can provide additional functionality depending on whether we run a module as a program or import it.

Related

How to make a Windows shortcut to run a function in a Python script?

I am trying to find a way to create a Windows shortcut that executes a function from a Python file.
The function being run would look something like this (it runs a command in the shell):
def function(command):
subprocess.run(command, shell = True, check = True)
I am aware that you can run cmd functions and commands directly with a shortcut, but I would like it to be controlled by Python.
I have little experience working with Windows shorcuts, so the best I can do is show you the following:
This is what I imagine it would like like.
After a quick Google search, the only help I can find is how to make a shortcut with Python, not how to run a function from it. So hopefully what I am asking is even possible?
Generally speaking AFAIK, you can't do it, however it could be done if the target script is written a certain way and is passed the name of the function to run as an argument. You could even add arguments to be passed to the function by listing them following its name in the shortcut.
The target script has to be set up with an if __name__ == '__main__': section similar to what is shown below which executes the named function it is passed as a command line argument. The input() call at the end is there just to make the console window stay open so what is printed can be seen.
target_script.py:
def func1():
print('func1() running')
def func2():
print('func2() running')
if __name__ == '__main__':
from pathlib import Path
import sys
print('In module', Path(__file__).name)
funcname = sys.argv[1]
vars()[funcname]() # Call named function.
input('\npress Enter key to continue...')
To make use of it you would need to create a shortcut with a Target: set to something like:
python D:\path_to_directory\target_script.py func1
Output:
In module target_script.py
func1() running
press Enter key to continue...
Generalizing
It would also be possible to write a script that could be applied to other scripts that weren't written like target_script.
run_func_in_module.py:
import importlib.util
from pathlib import Path
import sys
mod_filepath = Path(sys.argv[1])
funcname = sys.argv[2]
# Import the module.
spec = importlib.util.spec_from_file_location(mod_filepath.stem, mod_filepath)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
# Call the specified function in the module.
mod_func = getattr(module, funcname)
mod_func()
To make use of this version you would need to create a shortcut with a Target: set to something like:
python D:\path_to_directory\run_func_in_module.py D:\another_directory\target_script.py func2
Note that the target_script.py would no longer need the if __name__ == '__main__': section at the end (although having one would do no harm).

Gradescope failed to execute [duplicate]

I have this code:
import sys
def random(size=16):
return open(r"C:\Users\ravishankarv\Documents\Python\key.txt").read(size)
def main():
key = random(13)
print(key)
When I try running the script, there are no errors, but nothing appears to happen. I expected it to print some content from the key file, but nothing is printed.
What is wrong? How do I make the code run?
You've not called your main function at all, so the Python interpreter won't call it for you.
Add this as the last line to just have it called at all times:
main()
Or, if you use the commonly seen:
if __name__ == "__main__":
main()
It will make sure your main method is called only if that module is executed as the starting code by the Python interpreter. More about that here: What does if __name__ == "__main__": do?
If you want to know how to write the best possible 'main' function, Guido van Rossum (the creator of Python) wrote about it here.
Python isn't like other languages where it automatically calls the main() function. All you have done is defined your function.
You have to manually call your main function:
main()
Also, you may commonly see this in some code:
if __name__ == '__main__':
main()
There's no such main method in python, what you have to do is:
if __name__ == '__main__':
main()
Something does happen, it just isn't noticeable
Python runs scripts from top to bottom. def is a statement, and it executes when it is encountered, just like any other statement. However, the effect of this is to create the function (and assign it a name), not to call it. Similarly, import is a statement that loads the other module (and makes its code run top to bottom, with its own global-variable context), and assigns it a name.
When the example code runs, therefore, three things happen:
The code for the sys standard library module runs, and then the name sys in our own module's global variables is bound to that module
A function is created from the code for random, and then the name random is bound to that function
A function is created from the code for main, and then the name main is bound to that function
There is nothing to call the functions, so they aren't called. Since they aren't called, the code inside them isn't run - it's only used to create the functions. Since that code doesn't run, the file isn't read and nothing is printed.
There are no "special" function names
Unlike in some other languages, Python does not care that a function is named main, or anything else. It will not be run automatically.
As the Zen of Python says, "Explicit is better than implicit". If we want a function to be called, we have to call it. The only things that run automatically are the things at top level, because those are the instructions we explicitly gave.
The script starts at the top
In many real-world scripts, you may see a line that says if __name__ == '__main__':. This is not "where the script starts". The script runs top to bottom.
Please read What does if __name__ == "__main__": do? to understand the purpose of such an if statement (short version: it makes sure that part of your top-level code is skipped if someone else imports this file as a module). It is not mandatory, and it does not have any kind of special "signalling" purpose to say where the code starts running. It is just a perfectly normal if statement, that is checking a slightly unusual condition. Nothing requires you to use it in a script (aside from wanting to check what it checks), and nothing prevents you from using it more than once. Nothing prevents you from checking whether __name__ is equal to other values, either (it's just... almost certainly useless).
You're not calling the function. Put main() at the bottom of your code.

Imported function is being executed twice

When I am importing a function from a module into a script of another file and then run it, the function starts all over after it has finished although it is supposed to run only once.
If I, however, only run the cell with the imported function then the function sometimes only runs once which is confusing because I have deactivated everything else in the script so it should not make a difference, should it? But sometimes it also runs twice which is even more confusing because I have not changed anything in the meantime (at least not that I would know).
One difference is that when I run the entire script the console says
Reloaded modules: mytestmodule
after the script has been executed while when I only run the cell this does not show up. I do not know if this matters though.
Either way, here is the function (from the file mytestmodule.py):
def equation():
print("Hi! Please enter your name.")
name=input()
print("Hello "+name+"! Please enter an integer that is bigger than 1 but smaller than 10.")
answertrue="That is correct!"
answerfalse="That integer is not correct. Please try again."
answernointeger="That is not an integer. Please try again."
biggersmaller=True
while biggersmaller:
task=input()
try:
if int(task)>1 and int(task)<10:
return(print(answertrue))
break
else:
print(answerfalse)
except ValueError:
print(answernointeger)
equation()
And here is the script of the import in the other file:
import mytestmodule
mytestmodule.equation()
This is because inside your mytestmodule.py you are calling the equation function already.
Either:
Remove the call of equation from mytestmodule.py
or
Don't call the function after importing it

Python nameError help when importing from another file

I have a function in maya that imports in other functions and creates a shelf with buttons for specific functions. I have a function that has a scriptJob command that works fine. if I import that file in manually and not through the shelf button, but gives a NameError when using the shelf script to run it.
This is an example of the script
myShelf.py file:
import loopingFunction
loopingFunction.runThis()
loopingFunction.py file:
import maya.cmds as mc
def setSettings():
#have some settings set before running this
runThis()
def runThis():
print "yay this ran"
evalDeferred(mc.scriptJob(ro=True,ac=["'someMesh.outMesh',runThis"])
if I run this through the shelf function, I get a runThis nameError is not defined and if I try modifying the scriptJob command to loopingFunction.runThis, I get a nameError loopingFunction is not defined(not sure if using loopingFunction.runThis is even correct, to be honest)
Not sure how I can get around this without having to manually import in the function rather than through the shelf file.
Using string references for callback functions like this often leads to scope problems. (More on that, and why not to use strings, here)
If you pass the function directly to the callback as an object, instead of using a string, it should work correctly as along as you have actually imported the code.
in this case you want an evalDeferred -- do you actually need it? -- so it helps to add a little function around the actual code so that the scriptjob creation actually happens later -- otherwise it will get evaluated before the deferral is scheduled.
def runThis():
print "callback ran"
def do_scriptjob():
cmds.scriptJob(ro=True, ac=('someMesh.outMesh', runThis)
cmds.evalDeferred(do_scriptjob)
In both runThis and do_scriptjob I did not add the parens -- we are letting the evalDeferred and the scriptJob have the function objects to call when they are ready. Using the parens would pass the results of the functions which is not what you want here.
Incidentally it looks like you're trying to create a new copy of the scriptJob inside the scriptJob itself. It'd be better to just drop the runOnce flag and leave the scriptJob lying around -- if something in runThis actually affected the someMesh.outMesh attribute, your maya will go into an infinite loop. I did not change the structure in my example, but I would not recommend writing this kind of self-replicating code if you can possibly avoid it.
You have a problem of nested/maya scope variables
mc.scriptJob(ro=True,ac=["'someMesh.outMesh',runThis"]
This line is a maya command string that is evaluated in the main maya scope (like a global)
As your function have a namespace with the import : 'loopingFunction', you need to enforce it in the string command.
import loopingFunction
loopingFunction.runThis()
You should write
evalDeferred(mc.scriptJob(ro=True,ac=["'someMesh.outMesh',loopingFunction.runThis"])
If you want something more general, you can do :
def runThis(ns=''):
print "yay this ran"
if ns != '':
ns += '.'
evalDeferred(mc.scriptJob(ro=True,ac=["'someMesh.outMesh',{}runThis".format(ns)])
and then run in shelf :
import loopingFunction
loopingFunction.runThis('loopingFunction')
like this you can write any formof namepsaces :
import loopingFunction as loopF
loopF.runThis('loopF')

Writing a Python module that can tell when it's hit with Spyder's UMD (user module deleter)

Spyder's UMD is usually great for me but periodically I trip myself when writing a module that I don't want to delete and reload. I know I can control the UMD via Tools > Preferences > Console > Advanced settings > User Module Deleter. But I would also like to be able to mark certain modules I write as non-UMD friendly in the code of the module itself.
In a perfect world I would just write something like
assert_no_umd()
which would throw an exception if the module is hit by the UMD. It would be fine if the code was tripped by any reloading of the module, whether by UMD or otherwise.
Note that this is different from Method that gets called on module deletion in Python because that question is about cleaning up a database connection which only needs to be done once, and therefore can be done with atexit.
(Spyder dev here) If I understand you correctly, this would be my assert_no_umd function:
import os
def assert_no_umd():
mod = __file__
if os.environ.get("UMD_ENABLED", "").lower() == "true":
namelist = os.environ.get("UMD_NAMELIST", None)
if namelist is not None:
namelist = namelist.split(',')
if mod not in namelist:
raise ValueError('UMD active!!')

Categories

Resources