I made a code on Raspberry pi that clone one usb stick to another. It works fine when I run it from python shell. But when I tried to run it using /.bashrc when I boot up or open terminal I get error TypeError: __init__() got an unexpected keyword argument 'text'. I fugured out that by ommitting text argumet I fix this error but then my code fail to read from stderr.
My code:
comm = 'sudo dd if=/dev/sda of=/dev/sdb status=progress'
cloning = subprocess.Popen(comm, shell = True, stderr = PIPE, text = True)
while True:
output = cloning.stderr.readline()
progress_bar(output)
Above code works when run directly in python. When run using /.bashrc - Command get executed when 'text' argument deleted from code. But code get stuck at .readline().
Connected question:Getting stdout from console
Thanks for help in advance.
Related
I am currently working with a software package that allows you to create Python scripts and execute them from inside that package. The results of any script are saved back into the program. When the script executes, it does not show a command prompt window.
Is there an easy way to open a command prompt window from inside the script and pass over information for display, such as a dataframe header, a string or a list of values?
I have found from earlier SO posts that I can use:
import os
os.system('cmd /k "Some random text"')
This works as expected, but when I use the following code:
x = str(2 * 2)
output= f'cmd /k "{x}"'
os.system(output)
The number 4 is passed to the command window, but the following message appears:
'4' is not recognized as an internal or external command, operable program or batch file.
The answer is in the question.
'4' is not recognized as an internal or external command, operable program or batch file.
Open cmd and type anything it will give error unless we type something which is recognized by cmd. e.g a help command.
if there is something we want to type in cmd and let it get processed/printed on console we use a command
echo
in your program only the echo command was missing, which will let your output get printed on cmd.
Last but not the least, always remember the ZEN of Python
Use subprocess instead
The `subprocess` has some more benefits compared to `Os`:
The subprocess module provides a consistent interface to creating and working with additional processes.
It offers a higher-level interface than some of the other available modules, and is intended to replace functions such as os.system(), os.spawn*(), os.popen*(), popen2.*() and commands.*().
Reference
If you want to write something like to print 4 in another cmd tab, do like this:
import subprocess
var = '4'
subprocess.Popen(['start','cmd','/k','echo',var], shell = True, stdin = subprocess.PIPE, stdout = subprocess.PIPE, text = True)
Result:
It opens another cmd tab and passes a command such as echo var.
I have two different types of Arduino Mega 2560 boards. One can be detected easily using the command mode and the other chgport. I have no problem setting up subprocess to run the command mode. When I am setting up subprocess.run to run the command chgport, I do not get the same answer I got by manually typing the chgport into the command prompt.
I type chgport into Windows command line and I got:
COM5 = \Device\Serial2
I set up Python 3.7.2 command:
subprocess.run(["chgport"],shell=True,stdout=subprocess.PIPE)
I got this output, which is not what I expected:
CompletedProcess(args=['chgport'], returncode=1, stdout=b'')
I expected:
stdout=b'COM5 = \Device\Serial2'
Code that I had tried:
a=subprocess.run(["chgport"],shell=True,stdout=subprocess.PIPE)
print(a.stdout.decode('utf-8'))
Hi I gave up on using subprocess so I use os. The code below works. First I redirect the output from mode into a file and then read the file.
import os
import sys
dir=os.popen("echo %cd%").readlines()[0].strip("\n")+"\\"
os.popen("cd "+dir+ """&& mode>"""+dir+"junk")
com = os.popen("more "+dir+"junk | findstr COM""").readlines()
os.popen("del "+dir+"junk")
port=com[0]
first=port.find("COM")
second=port.find(":")
print(port[first:second])
So i have a script from Python that connects to the client servers then get some data that i need.
Now it will work in this way, my bash script from the client side needs input like the one below and its working this way.
client.exec_command('/apps./tempo.sh' 2016 10 01 02 03))
Now im trying to get the user input from my python script then transfer it to my remotely called bash script and thats where i get my problem. This is what i tried below.
Below is the method i tried that i have no luck working.
import sys
client.exec_command('/apps./tempo.sh', str(sys.argv))
I believe you are using Paramiko - which you should tag or include that info in your question.
The basic problem I think you're having is that you need to include those arguments inside the string, i.e.
client.exec_command('/apps./tempo.sh %s' % str(sys.argv))
otherwise they get applied to the other arguments of exec_command. I think your original example is not quite accurate in how it works;
Just out of interest, have you looked at "fabric" (http://www.fabfile.org ) - this has lots of very handy funcitons like "run" which will run a command on a remote server (or lots of remote servers!) and return you the response.
It also gives you lots of protection by wrapping around popen and paramiko for hte ssh login etcs, so it can be much more secure then trying to make web services or other things.
You should always be wary of injection attacks - Im unclear how you are injecting your variables, but if a user calls your script with something like python runscript "; rm -rf /" that would have very bad problems for you It would instead be better to have 'options' on the command, which are programmed in, limiting the users input drastically, or at least a lot of protection around the input variables. Of course if this is only for you (or trained people), then its a little easier.
I recommend using paramiko for the ssh connection.
import paramiko
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.connect(server, username=user,password=password)
...
ssh_client.close()
And If you want to simulate a terminal, as if a user was typing:
chan=ssh_client.invoke_shell()
chan.send('PS1="python-ssh:"\n')
def exec_command(cmd):
"""Gets ssh command(s), execute them, and returns the output"""
prompt='python-ssh:' # the command line prompt in the ssh terminal
buff=''
chan.send(str(cmd)+'\n')
while not chan.recv_ready():
time.sleep(1)
while not buff.endswith(prompt):
buff+=ssh_client.chan.recv(1024)
return buff[:len(prompt)]
Example usage: exec_command('pwd')
And the result would even be returned to you via ssh
Assuming that you are using paramiko you need to send the command as a string. It seems that you want to pass the command line arguments passed to your Python script as arguments for the remote command, so try this:
import sys
command = '/apps./tempo.sh'
args = ' '.join(sys.argv[1:]) # all args except the script's name!
client.exec_command('{} {}'.format(command, args))
This will collect all the command line arguments passed to the Python script, except the first argument which is the script's file name, and build a space separated string. This argument string is them concatenated with the bash script command and executed remotely.
I have found this odd issue where running the following code in a python shell works but running a python file with the code in it does not.
import serial
connection = serial.Serial("/dev/ttyACM0", 19200)
write = connection.write("h\r".encode())
print(connection.read(connection.inWaiting()))
connection.close()
running directly in python3 shell gives the following output (which is correct):
b'halt ack\r\n'
while running a python file gives this output:
b''
I have no idea what is causing the inconsistency, does anyone know? No amount of delay seems to fix the problem.
Can someone please explain to me piece by piece, what the following does? My code won't run and this part was provided. I've tested all of my code in iPython notebook and everything works, so I don't know if the problem is because of this block below.
def main():
args = sys.argv[1:]
if not args:
print 'usage: [--summaryfile] file [file ...]'
sys.exit(1)
summary = False
if args[0] == '--summaryfile':
summary = True
del args[0]
# ... my code ....
Update: I tried to do as Simon suggested. I opened up iPython and typed the following in the command line:
ipython 'assignment.py' --summaryfile
I tried variations of this and I keep getting a syntax error.
How do I run this?
Am I restricted to iPython only?
It basically checks to see if --summaryfile has been passed as an argument when you run the script
If no arguments have been passed, then it will print a line telling you how to use the script and then exit. summary is now set to false
If --summaryfile has been passed, then it will set summary = True and continue running the rest of your code
I'm not sure that you can enter arguments like that in ipython, so presumably your code will always exit because it doesnt find any arguments
EDIT:
For some reason I automatically associated ipython with ipython notebook. You can pass arguments with ipython. See here:
How to pass command line arguments to ipython
In your case, try adding --summaryfile as an argument when you run your script through ipython
If you're running this from ipython notebook, there are a couple of things you can try:
Remove that section of code and just set summary = True. The rest of your code should run, but without seeing everything its hard to say what impact this may have on the rest of your code
You can save your script as a python .py file, and use ipython magic to run the code from within notebook. You can pass arguments when you're running that script from within notebook. Check this: https://ipython.org/ipython-doc/dev/interactive/magics.html#magic-run
If you have all the code in a regular .py file (outside of a notebook) you can run and pass an argument using the command line. Navigate to the directory where the script file is and run ipython filename.py --summaryfile
A very rudimentary command line argument parser.
It checks for the command line except the executable's name itself (sys.argv[1:]). If it's empty, dump help message and fail. If the first argument is "--summaryfile", set some flag.