Python if statement returning - python

I am having trouble with what is presumably a simple if statement. I am trying to pass through the type of VM file format to use. Even if I put VMDK or VHD, it still comes back with VMDK is an invalid type or VHD is an invalid type.
import sys
vmtype = sys.argv[3]
vmtype = str(vmtype).strip().upper()
## File format check
if vmtype is not ("VHD") or ("VMDK"):
print vmtype + " is an invalid type"
sys.exit()
I have tried the if statement with != and not putting the parameters in parentheses. I have searched the web for a while and have tried what I have found and am still running into the same issue.
FYI I am running Python 2.6.5

Try:
if vmtype not in ("VHD", "VMDK"):
Your current code parses as:
if (vmtype is not ("VHD")) or ("VMDK"):
Which is obviously wrong. Since ("VMDK") is a truthy value, the whole statement always be true. Therefore the if statement will always execute.
Note that even if you tried
if vmtype is not "VHD":
It would not work, because is tests identity, not value. You would use:
if vmtype != "VHD":

Related

How to send an argument to another file in python 3

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.

Python: Subprocess works different to terminal. What I have to change?

I have to Python scripts: Tester1.py and Tester2.py.
Within Tester1 I want to start from time to time Tester2.py. I also want to pass Tester2.py some arguments. At the moment my code looks like this:
Tester1:
subprocess.call(['python3 Tester2.py testString'])
Tester2:
def start():
message = sys.argv[1]
print(message)
start()
Now my problem: If I run with my terminal Tester2 like 'python3 Tester2.py testString'my console prints out testString. But if I run Tester1 and Tester1 tries to start Tester2, I get an IndexError: "list index out of range".
How do I need to change my code to get everything working?
EDIT:
niemmi told me that I have to change my code to:
subprocess.call(['python3', 'Tester2.py', 'testString'])
but now I get a No such file or directory Error although both scripts are in the same directory. Someone knows why?
You need to provide the arguments either as separate elements on a list or as a string:
subprocess.call(['python3', 'Tester2.py', 'testString'])
# or
subprocess.call('python3 Tester2.py testString')
Python documentation has following description:
args is required for all calls and should be a string, or a sequence of program arguments. Providing a sequence of arguments is generally preferred, as it allows the module to take care of any required escaping and quoting of arguments (e.g. to permit spaces in file names). If passing a single string, either shell must be True (see below) or else the string must simply name the program to be executed without specifying any arguments.

Error in default programming of Google's Python exercise 'Copyspecial'

I get an IndexError: list index out of range error when using the --todir option in Google's Python Exercise copyspecial.py. How can I resolve this issue? What confuses me the most is that the part of code causing it is what was written by the instructor (from Google/Standford). I can only assume some syntactic error has spilled into other lines of code or that built in function syntax has changed since Python 2.7. This exercise code was written in 2.7.
The file works when no option is used, as so:
Printing list of special files
C:.\gpe\copyspecial\xyz__hello__.txt
C:.\gpe\copyspecial\zz__something__.jpg
done
This is the error:
The code:
def main():
# This basic command line argument parsing code is provided.
# Add code to call your functions below.
# Make a list of command line arguments, omitting the [0] element
# which is the script itself.
args = sys.argv[1:]
if not args:
print "usage: [--todir dir][--tozip zipfile] dir [dir ...]";
sys.exit(1)
# todir and tozip are either set from command line
# or left as the empty string.
# The args array is left just containing the dirs.
todir = ''
if args[0] == '--todir':
todir = args[1]
del args[0:2]
tozip = ''
if args[0] == '--tozip':
tozip = args[1]
del args[0:2]
if len(args) == 0:
print "error: must specify one or more dirs"
sys.exit(1)
# +++your code here+++
# Call your functions
All the aforementioned code is straight from google.com. My code comes before main() is defined and after where it says # +++your code here+++
I have spent hours trying to resolve this. I've learned a lot, but not the solution.
I've tried changing indentations.
I've tried doing sys.exit(1) nest under the '--todir' 'if', but the program keeps running down into the 'if tozip' part, which leads me to believe it's syntactical. But I can't find a misplaced () or :. I also checked indentations.
I've tried adding an 'if args[0]:' check, but it doesn't work, because as I later learned, although an empty list ('args[0]' = []), Python does not interpret it as an actual 'False' value.
The list goes on
I really appreciate the opportunity to have my question heard by the community at stackoverflow, and even more so as a first time poster.
As far as I can see your third try should work if you do it right:
tozip = ''
if args and args[0] == '--tozip':
tozip = args[1]
del args[0:2]
This actually checks the list args. If it is empty ([]), it is considered False and the second test args[0] == '--tozip' does not get evaluated.
Your problem is that args itself is an empty list which does evaluate to False (see https://docs.python.org/2/library/stdtypes.html#truth-value-testing), hence you cannot access args[0] and checking for it results in the same Indexerror.
However, you would still get an IndexError if you only pass one of the parameters without the argument because you access args[1] without testing.
EDIT (Why doesn't the code run as is?): I don't think any python versions >=2.4 would interpret this differently but I have no proof. This argument passing is very basic. Checking for malformed user input is always quite "annoying" because you have to handle every possible input which results in a lot of code. If you want to go into more detail of argument passing I recommend the argparse module (2.7, 3.5). My feeling is that to avoid having a large part of the exercise file that has nothing to do with the exercise they just left it that simple. If you don't supply at least one file path as a parameter you will get an error message in the next step anyway:
if len(args) == 0:
print "error: must specify one or more dirs"
sys.exit(1)
So the code does run as is. You just have to supply the right parameters.

Syntax error with Cloud 9?

I'm new to Cloud 9, and have made a script. I want the code to appear at the url https://python-william1835.c9.io and I receive the following message:
Important: use os.getenv(PORT, 8080) as the port and os.getenv(IP,0.0.0.0) as the host in your scripts!
when I run it.
So I put it in the script (along with import os of course). And when I run it again, it says:
File "/home/ubuntu/workspace/Python Projects/Python Enigma Program/main.py", line 14
os.getenv(IP, 0.0.0.0)
^
SyntaxError: invalid syntax
Can you tell me why it does this?
You get a SyntaxError because the literal 0.0.0.0 is syntactically invalid.
The message you're receiving is a bit misleading in this specific case. Additionally, the documentation page for os.getenv is unfortunately not as verbose as one would want.
But, if you look at the source code for getenv you'll see that all arguments must be of type str:
def getenv(key, default=None):
"""Get an environment variable, return None if it doesn't exist.
The optional second argument can specify an alternate default.
key, default and the result are str."""
return environ.get(key, default)
Changing your calls to:
os.getenv("PORT", "8080")
os.getenv("IP", "0.0.0.0")
Should work and you should have no problem using them.

How can I add a command to the Python interactive shell?

I'm trying to save myself just a few keystrokes for a command I type fairly regularly in Python.
In my python startup script, I define a function called load which is similar to import, but adds some functionality. It takes a single string:
def load(s):
# Do some stuff
return something
In order to call this function I have to type
>>> load('something')
I would rather be able to simply type:
>>> load something
I am running Python with readline support, so I know there exists some programmability there, but I don't know if this sort of thing is possible using it.
I attempted to get around this by using the InteractivConsole and creating an instance of it in my startup file, like so:
import code, re, traceback
class LoadingInteractiveConsole(code.InteractiveConsole):
def raw_input(self, prompt = ""):
s = raw_input(prompt)
match = re.match('^load\s+(.+)', s)
if match:
module = match.group(1)
try:
load(module)
print "Loaded " + module
except ImportError:
traceback.print_exc()
return ''
else:
return s
console = LoadingInteractiveConsole()
console.interact("")
This works with the caveat that I have to hit Ctrl-D twice to exit the python interpreter: once to get out of my custom console, once to get out of the real one.
Is there a way to do this without writing a custom C program and embedding the interpreter into it?
Edit
Out of channel, I had the suggestion of appending this to the end of my startup file:
import sys
sys.exit()
It works well enough, but I'm still interested in alternative solutions.
You could try ipython - which gives a python shell which does allow many things including automatic parentheses which gives you the function call as you requested.
I think you want the cmd module.
See a tutorial here:
http://wiki.python.org/moin/CmdModule
Hate to answer my own question, but there hasn't been an answer that works for all the versions of Python I use. Aside from the solution I posted in my question edit (which is what I'm now using), here's another:
Edit .bashrc to contain the following lines:
alias python3='python3 ~/py/shellreplace.py'
alias python='python ~/py/shellreplace.py'
alias python27='python27 ~/py/shellreplace.py'
Then simply move all of the LoadingInteractiveConsole code into the file ~/py/shellreplace.py Once the script finishes executing, python will cease executing, and the improved interactive session will be seamless.

Categories

Resources