How to run a Powershell function through a Python script - python-2.7

I am trying to create a translator-type program in Python (this is 2.7, if that is important). I want to receive user input, translate it, and then print their output to the screen. That part is not difficult, but I also want to export it to a text file. I am using Powershell for that, with the subprocess module. The Powershell script is very short, and all it does is asks for the user to copy and paste the Python translation into an input. It then calls New-Item to create a file and gives it the value option as the Python translation.
Python code:
def translator:
inquiry = raw_input("Leetspeak trans query: ") #Enter query
inquiry = inquiry.lower() #Change all to lowercase, so that everything gets translated
newPrint1 = "" #The new string that gets returned to them at the end
level = raw_input("What type of 1337 do you want? 1 for basic, 2 for intermediate, \
3 for intermediate-advanced, and 4 for ultimate.")
if level == "1":
from b4s1c_l33t import leetkey
elif level == "2":
from In73rm3d1473_1337 import leetkey
elif level == "3":
from In7_4DV import leetkey
from In7_4DV import combokey
elif level == "4":
from U17IM473_1337 import leetkey
from U17IM473_1337 import combokey
for char in inquiry:
if char in leetkey:
newPrint1 += leetkey[char]
else:
newPrint1 += char #Checks to see if the char is in the single-char list, then appends it accordingly
if int(level) >= 3:
for item in combokey:
if item in newPrint1:
newPrint1 = newPrint1.replace(item, combokey[item])
print newPrint1 #Print answer
question = raw_input(r"Do you want to translate some more? Type Y or N ") #Asks if they want to do more
question = question.lower() #Changes it to lowercase, for sending through the if loop
if question == "y" or question == "Y":
translator() #If answer is yes, program calls the entire function again
elif question != "y" and question != "n" and question != "Y" and question != "N":
print "I didn't quite catch that."
ps = raw_input("Would you like to export your leetness to a file? Type Y or N ")
if ps == "Y" or ps == "y":
import subprocess
subprocess.call(["C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\powershell.exe", ". \"./1337Export.ps1\";", "&export"])
else:
print r"0|<. 600|)|3`/3!"
translator() #calls the function once
Powershell script:
Function export(){
$param = Read-Host("Copy-paste the translation from above here! ")
New-Item C:\Scripts\1337\1337ness.txt -type file -value $param
}
But I also know that the script was working perfectly up until I added the Powershell to it, so the problem is either in my usage of the subprocess module or in the Powershell script itself. I am a somewhat-medium-beginner at using Powershell, so any help will be greatly appreciated. Either that, or if there is a way to create the new file and write data to it in Python itself, that would be greatly appreciated.
Thanks,
Prem
Note: in the Python script, the leetkey and combokey are in separate files that are imported based on the value of the variable level.
UPDATE: I looked at the page here, and the subprocess code in the Python script is what I found in that page. It did not work, but instead threw an error saying that the export function does not exist, which it obviously does... in Powershell. Thanks again!

Your parameter construction is off. You want to run the following commandline in PowerShell:
. "./1337Export.ps1"; & export
which basically means "dot-source (IOW import) the script 1337Export.ps1 from the current working directory, then call (&) the function export".
The cleanest way to do this is to put the statement in a scriptblock:
&{. "./1337Export.ps1"; & export}
and pass that scriptblock as a single argument, so your Python statement should look like this:
subprocess.call(["C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\powershell.exe", '-Command', '&{. "./1337Export.ps1"; & export}'])
Of course you need to make sure that 1337Export.ps1 actually exists in the current working directory when you execute the Python script.

You have to do two things:
1) dot source the script (which is similar to python's import), and
2) subprocess.call.
import subprocess
subprocess.call(["C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\powershell.exe", ". \"./SamplePS\";", "&export"])
Note: I have assumed that both the .py and .ps1 are residing in the same directory and the name of the powershell script is "SamplePS" and from that script I am using the function "export"
Hope it helps

Related

Python script executable crashes immediately

I work with python 2.7 and I have a python script that ssh to remote servers and it works fine using python command from cmd but when I convert this script to executable file using py2exe or cx_freeze or Pyinstaller and try to run it, the window open and close immediately like if the program crashes. I tried another simple scripts like print function or some math function the executable files work fine so any one could help what would be the reason?
Thanks
Here is my code:
import sys
import paramiko
import getpass
def print_menu():
print 30 * "-", "MENU", 30 * "-"
print "1. LAB1"
print "2. LAB2"
print "3. LAB3"
print "4. Exit"
print 67 * "-"
def ssh_command(ssh):
while True:
command = raw_input("Enter command or q :")
ssh.invoke_shell()
stdin, stdout, stderr = ssh.exec_command(command)
stdout = stdout.readlines()
if command == "q":
break
for line in stdout:
if "Size" in line:
print "found the string"
break`enter code here`
else:
print "There was no output for this command"
def ssh_connect(host, user, password):
try:
ssh = paramiko.SSHClient()
print('Connecting...')
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=host, username=user, password=password)
ssh_command(ssh)
except Exception as e:
print('Connection Failed')
print(e)
def ssh_close():
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.close()
def credentials(host):
user = raw_input("Username:")
password = getpass.getpass("password for " + user + ":")
ssh_connect(host, user, password)
loop = True
while loop:
print_menu()
choice = input("Enter your choice [1-3]: ")
if choice == 1:
credentials('x.x.x.x')
elif choice == 2:
credentials('x.x.x.x')
elif choice == 3:
credentials('x.x.x.x')
elif choice == 4:
loop = False
print "Closing SSH connection"
print
ssh_close()
else:
raw_input("Wrong option selection. Enter any key to try again..")
You can check the error by running the exe file in command prompt.
This will give you an upper hand.
Especially in cx_freeze you have to mention the dependencies.
I think you are facing some dependency problem.
When you specifiy --debug=all after your pyinstall command when packaging, you will see specific errors when starting your applicataion in the dist folder.
Read here https://pyinstaller.readthedocs.io/en/stable/when-things-go-wrong.html to get more information on debugging specific errors and how to fix them.
you can use the pyinstaller with -F argument to fully package the python interpreter then open windows cmd and run it
pyinstaller -F <your_script>.py
Worry not, my friend! Just add a window.mainloop() call at the end of your program. Then, everything should work properly. I was stumped by the same problem got revelation from your words:
I tried another simple scripts like print function or some math function the executable files work fine
So, I compared both programs side by side and received my answer.
Running pyinstaller with the F flag should solve the problem of immediate close after startup.

The glob.glob function to extract data from files

I am trying to run the script below. The intention of the script is to open different fasta files one after the other, and extract the geneID. The script works well if I don't use the glob.glob function. I get this message TypeError: coercing to Unicode: need string or buffer, list found
files='/home/pathtofiles/files'
#print files
#sys.exit()
for file in files:
fastas=sorted(glob.glob(files + '/*.fasta'))
#print fastas[0]
output_handle=(open(fastas, 'r+'))
genes_files=list(SeqIO.parse(output_handle, 'fasta'))
geneID=genes_files[0].id
print geneID
I am running of ideas on how to direct the script to open when file after another to give me the require information.
I see what you are trying to do, but let me first explain why your current approach is not working.
You have a path to a directory with fasta files and you want to loop over the files in that directory. But observe what happens if we do:
>>> files='/home/pathtofiles/files'
>>> for file in files:
>>> print file
/
h
o
m
e
/
p
a
t
h
t
o
f
i
l
e
s
/
f
i
l
e
s
Not the list of filenames you expected! files is a string and when you apply a for loop on a string you simply iterate over the characters in that string.
Also, as doctorlove correctly observed, in your code fastas is a list and open expects a path to a file as first argument. That's why you get the TypeError: ... need string, ... list found.
As an aside (and this is more a problem on Windows then on Linux or Mac), but it is good practice to always use raw string literals (prefix the string with an r) when working with pathnames to prevent the unwanted expansion of backslash escaped sequences like \n and \t to newline and tab.
>>> path = 'C:\Users\norah\temp'
>>> print path
C:\Users
orah emp
>>> path = r'C:\Users\norah\temp'
>>> print path
C:\Users\norah\temp
Another good practice is to use os.path.join() when combining pathnames and filenames. This prevents subtle bugs where your script works on your machine bug gives an error on the machine of your colleague who has a different operating system.
I would also recommend using the with statement when opening files. This assures that the filehandle gets properly closed when you're done with it.
As a final remark, file is a built-in function in Python and it is bad practice to use a variable with the same name as a built-in function because that can cause bugs or confusion later on.
Combing all of the above, I would rewrite your code like this:
import os
import glob
from Bio import SeqIO
path = r'/home/pathtofiles/files'
pattern = os.path.join(path, '*.fasta')
for fasta_path in sorted(glob.glob(pattern)):
print fasta_path
with open(fasta_path, 'r+') as output_handle:
genes_records = SeqIO.parse(output_handle, 'fasta')
for gene_record in genes_records:
print gene_record.id
This is way I solved the problem, and this script works.
import os,sys
import glob
from Bio import SeqIO
def extracting_information_gene_id():
#to extract geneID information and add the reference gene to each different file
files=sorted(glob.glob('/home/path_to_files/files/*.fasta'))
#print file
#sys.exit()
for file in files:
#print file
output_handle=open(file, 'r+')
ref_genes=list(SeqIO.parse(output_handle, 'fasta'))
geneID=ref_genes[0].id
#print geneID
#sys.exit()
#to extract the geneID as a reference record from the genes_files
query_genes=(SeqIO.index('/home/path_to_file/file.fa', 'fasta'))
#print query_genes[geneID].format('fasta') #check point
#sys.exit()
ref_gene=query_genes[geneID].format('fasta')
#print ref_gene #check point
#sys.exit()
output_handle.write(str(ref_gene))
output_handle.close()
query_genes.close()
extracting_information_gene_id()
print 'Reference gene sequence have been added'

Python-Console (Anaconda 4.2.0 (64-bit)): Input is not taken as string but "variable"? [duplicate]

I am getting an error when I try to run this simple script:
input_variable = input("Enter your name: ")
print("your name is" + input_variable)
Let's say I type in "dude", the error I am getting is:
line 1, in <module>
input_variable = input("Enter your name: ")
File "<string>", line 1, in <module>
NameError: name 'dude' is not defined
I am running Mac OS X 10.9.1 and I am using the Python Launcher app that came with the install of Python 3.3 to run the script.
TL;DR
input function in Python 2.7, evaluates whatever your enter, as a Python expression. If you simply want to read strings, then use raw_input function in Python 2.7, which will not evaluate the read strings.
If you are using Python 3.x, raw_input has been renamed to input. Quoting the Python 3.0 release notes,
raw_input() was renamed to input(). That is, the new input() function reads a line from sys.stdin and returns it with the trailing newline stripped. It raises EOFError if the input is terminated prematurely. To get the old behavior of input(), use eval(input())
In Python 2.7, there are two functions which can be used to accept user inputs. One is input and the other one is raw_input. You can think of the relation between them as follows
input = eval(raw_input)
Consider the following piece of code to understand this better
>>> dude = "thefourtheye"
>>> input_variable = input("Enter your name: ")
Enter your name: dude
>>> input_variable
'thefourtheye'
input accepts a string from the user and evaluates the string in the current Python context. When I type dude as input, it finds that dude is bound to the value thefourtheye and so the result of evaluation becomes thefourtheye and that gets assigned to input_variable.
If I enter something else which is not there in the current python context, it will fail will the NameError.
>>> input("Enter your name: ")
Enter your name: dummy
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "<string>", line 1, in <module>
NameError: name 'dummy' is not defined
Security considerations with Python 2.7's input:
Since whatever user types is evaluated, it imposes security issues as well. For example, if you have already loaded os module in your program with import os, and then the user types in
os.remove("/etc/hosts")
this will be evaluated as a function call expression by python and it will be executed. If you are executing Python with elevated privileges, /etc/hosts file will be deleted. See, how dangerous it could be?
To demonstrate this, let's try to execute input function again.
>>> dude = "thefourtheye"
>>> input("Enter your name: ")
Enter your name: input("Enter your name again: ")
Enter your name again: dude
Now, when input("Enter your name: ") is executed, it waits for the user input and the user input is a valid Python function invocation and so that is also invoked. That is why we are seeing Enter your name again: prompt again.
So, you are better off with raw_input function, like this
input_variable = raw_input("Enter your name: ")
If you need to convert the result to some other type, then you can use appropriate functions to convert the string returned by raw_input. For example, to read inputs as integers, use the int function, like shown in this answer.
In python 3.x, there is only one function to get user inputs and that is called input, which is equivalent to Python 2.7's raw_input.
You are running Python 2, not Python 3. For this to work in Python 2, use raw_input.
input_variable = raw_input ("Enter your name: ")
print ("your name is" + input_variable)
Since you are writing for Python 3.x, you'll want to begin your script with:
#!/usr/bin/env python3
If you use:
#!/usr/bin/env python
It will default to Python 2.x. These go on the first line of your script, if there is nothing that starts with #! (aka the shebang).
If your scripts just start with:
#! python
Then you can change it to:
#! python3
Although this shorter formatting is only recognized by a few programs, such as the launcher, so it is not the best choice.
The first two examples are much more widely used and will help ensure your code will work on any machine that has Python installed.
I also encountered this issue with a module that was supposed to be compatible for python 2.7 and 3.7
what i found to fix the issue was importing:
from six.moves import input
this fixed the usability for both interpreters
you can read more about the six library here
You should use raw_input because you are using python-2.7. When you use input() on a variable (for example: s = input('Name: ')), it will execute the command ON the Python environment without saving what you wrote on the variable (s) and create an error if what you wrote is not defined.
raw_input() will save correctly what you wrote on the variable (for example: f = raw_input('Name : ')), and it will not execute it in the Python environment without creating any possible error:
input_variable = raw_input('Enter Your Name : ')
print("Your Name Is : " + (input_variable))
input_variable = input ("Enter your name: ")
print ("your name is" + input_variable)
You have to enter input in either single or double quotes
Ex:'dude' -> correct
dude -> not correct
For python 3 and above
s = raw_input()
it will solve the problem on pycharm IDE
if you are solving on online site exactly hackerrank then use:
s = input()
We are using the following that works both python 2 and python 3
#Works in Python 2 and 3:
try: input = raw_input
except NameError: pass
print(input("Enter your name: "))
There are two ways to fix these issues,
1st is simple without code change that is
run your script by Python3,
if you still want to run on python2 then
after running your python script, when you are entering the input keep in mind
if you want to enter string then just start typing down with "input goes with double-quote" and it will work in python2.7 and
if you want to enter character then use the input with a single quote like 'your input goes here'
if you want to enter number not an issue you simply type the number
2nd way is with code changes
use the below import and run with any version of python
from six.moves import input
Use raw_input() function instead of input() function in your code with any import
sanitise your code with str() function like str(input()) and then assign to any variable
As error implies: name 'dude' is not defined
i.e. for python 'dude' become variable here and it's not having any value of python defined type assignedso only its crying like baby so if we define a 'dude' variable and assign any value and pass to it, it will work but that's not what we want as we don't know what user will enter and moreover we want to capture the user input.
Fact about these method:
input() function: This function takes the value and type of the input you enter as it is without modifying it type. raw_input()
function: This function explicitly converts the input you give into type string,
Note: The vulnerability in input() method lies in the fact that
the variable accessing the value of input can be accessed by anyone
just by using the name of variable or method.
Try using raw_input rather than input if you simply want to read strings.
print("Enter your name: ")
x = raw_input()
print("Hello, "+x)
You could either do:
x = raw_input("enter your name")
print "your name is %s " % x
or:
x = str(input("enter your name"))
print "your name is %s" % x
For anyone else that may run into this issue, turns out that even if you include #!/usr/bin/env python3 at the beginning of your script, the shebang is ignored if the file isn't executable.
To determine whether or not your file is executable:
run ./filename.py from the command line
if you get -bash: ./filename.py: Permission denied, run chmod a+x filename.py
run ./filename.py again
If you've included import sys; print(sys.version) as Kevin suggested, you'll now see that the script is being interpreted by python3
Good contributions the previous ones.
import sys; print(sys.version)
def ingreso(nombre):
print('Hi ', nombre, type(nombre))
def bienvenida(nombre):
print("Hi "+nombre+", bye ")
nombre = raw_input("Enter your name: ")
ingreso(nombre)
bienvenida(nombre)
#Works in Python 2 and 3:
try: input = raw_input
except NameError: pass
print(input("Your name: "))
Enter your name: Joe
('Hi ', 'Joe', &lttype 'str'&gt)
Hi Joe, bye
Your name: Joe
Joe
Thanks!
You can change which python you're using with your IDE, if you've already downloaded python 3.x it shouldn't be too hard to switch. But your script works fine on python 3.x, I would just change
print ("your name is" + input_variable)
to
print ("your name is", input_variable)
Because with the comma it prints with a whitespace in between your name is and whatever the user inputted. AND: if you're using 2.7 just use raw_input instead of input.
Here is an input function which is compatible with both Python 2.7 and Python 3+:
(Slightly modified answer by #Hardian) to avoid UnboundLocalError: local variable 'input' referenced before assignment error
def input_compatible(prompt=None):
try:
input_func = raw_input
except NameError:
input_func = input
return input_func(prompt)
Also here is another alternative without a try block:
def input_compatible(prompt=None):
input_func = raw_input if "raw_input" in __builtins__.__dict__ else input
return input_func(prompt)

Recursive function not outputting intended value

I' m happy trouble understanding why the function below seems to be outputting None instead of 1 if the function doesn't have a vakud output on its first run through.
import win32com.client
BING_KEY = "XXXXXXXX"
import speech_recognition as sr
import win32com.client as wincl
s = sr.Recognizer()
def hey_pc():
print(" Hey PC = Command")
with sr.Microphone() as source:
audio = s.listen(source)
try:
x= (s.recognize_bing(audio, key=BING_KEY))
if x in ['hey PC']:
return 1
else: hey_pc()
except:
print('Try again')
hey_pc()
t = hey_pc()
print t
if the function outputs on its first run, I get the following output:
Hey PC == Command
1
But if it invokes its recursive property, I get a final output of None
Hey PC == Command
Hey PC == Command
Hey PC == Command
Hey PC == Command
None
or this
Hey PC == Command
Try again
Hey PC == Command
Hey PC == Command
None
I don't understand why I"m getting "None."
EDIT:
I've changed the second part of the code to this and played around more but still have the same problem:
t =hey_pc()
if t == 1:
speak = wincl.Dispatch("SAPI.SpVoice")
speak.Speak("This is the pc voice speaking")
import automation
automation.Apply_Command()
else:
hey_pc()
If my voice is recognized on its first attempt, the code under if t==1 is ran and there no problems, however if my voice is not recognized on its first attempt and recurvise portion of the code is activated, once my voice finally gets recognized, the program just ends (meaning the Python command prompt >>> pops up again). So I'm assuming it's the null value that's being passed on.
Still stumped. :(
Probably not the answer you're looking for, specifically, but it's generally because "if x in ['hey PC']" is NEVER true. The only condition where a number is returned (and thus setting a value) is your if statement. So, most likely, that if statement is never entered into.

How to replace string in multiple files in the folder?

I m trying to read two files and replace content of one file with content of other file in files present in folder which also has sub directories.
But its tell sub process not defined.
i'm new to python and shell script can anybody help me with this please?
import os
import sys
import os.path
f = open ( "file1.txt",'r')
g = open ( "file2.txt",'r')
text1=f.readlines()
text2=g.readlines()
i = 0;
for line in text1:
l = line.replace("\r\n", "")
t = text2[i].replace("\r\n", "")
args = "find . -name *.tml"
Path = subprocess.Popen( args , shell=True )
os.system(" sed -r -i 's/" + l + "/" + t + "/g' " + Path)
i = i + 1;
To specifically address your actual error, you need to import the subprocess module as you are making use of it (oddly) in your code:
import subprocess
After that, you will find more problems. I will try and keep it as simple as possible with my suggestions. Code first, then I will break it down. Keep in mind, there are more robust ways to accomplish this task. But I am doing my best to keep in mind your experience level and making it make your current approach as closely as possible.
import subprocess
import sys
# 1
results = subprocess.Popen("find . -name '*.tml'",
shell=True, stdout=subprocess.PIPE)
if results.wait() != 0:
print "error trying to find tml files"
sys.exit(1)
# 2
tml_files = []
for tml in results.stdout:
tml_files.append(tml.strip())
if not tml_files:
print "no tml files found"
sys.exit(0)
tml_string = " ".join(tml_files)
# 3
with open ("file1.txt") as f, open("file2.txt") as g:
while True:
# 4
f_line = f.readline()
if not f_line:
break
g_line = g.readline()
if not g_line:
break
f_line = f_line.strip()
g_line = g_line.strip()
if not f_line or not g_line:
continue
# 5
cmd = "sed -i -e 's/%s/%s/g' %s" % \
(f_line.strip(), g_line.strip(), tml_string)
ret = subprocess.Popen(cmd, shell=True).wait()
if ret != 0:
print "error doing string replacement"
sys.exit(1)
You do not need to read in your entire files at once. If they are large this could be a lot of memory. You can consume a line at a time, and you can also make use of what is called "context managers" when you open the files. This will ensure they close properly no matter what happens:
We start with a subprocess command that is run only once to find all your .tml files. Your version had the same command being run multiple times. If the search path is the same, then we only need it once. This checks the exit code of the command and quits if it failed.
We loop over stdout on the subprocess command, and add the stripped lines to a list. This is a more robust way of your replace("\r\n"). It removes whitespace. A "list comprehension" would be better suited here (down the line). If we didn't find any tml files, then we have no work to do, so we exit. Otherwise, we join them together in a space-separated string to be suitable for our command later.
This is called "context managers". You can open the file in a way that no matter what they will be closed properly. The file is open for the length of the context within that code block. We are going to loop forever, and break when appropriate.
We pull a line, one at a time, from each file. If either line is blank, we reached the end of the file and cannot do any more work, so we break out. We then strip the newlines, and if either string is empty (blank line) we still can't do any work, but we just continue to the next available line.
A modified version of your sed command. We construct the command string on each loop for the source and replacement strings, and tack on the tml file string. Bear in mind this is a very naive approach to the replacement. It really expects your replacement strings to be safe characters and not break the s///g sed format. But we run that with another subprocess command. The wait() simply waits for the return code, and we check it for an error. This approach replaces your os.system() version.
Hope this helps. Eventually you can improve this to do more checking and safe operations.