about if ... else ... getting stuck? - python

guys.
Recently,I ode a simple python program to do the job of synchronizing the Ubuntu repository, but I don't know why it is stuck at this conditional judgment, there is no standard output or error output, I tried to debug but still nothing, I see There is no problem here.
Please help.
# -*- coding:utf-8 -*-
# 2022-07-29
# 同步指定的ubuntu apt仓库到本地
# Synchronize the specified Ubuntu apt repository to the local
import subprocess
import os
rsync_server = 'rsync://rsync.mirrors.ustc.edu.cn/'
# rsync_dest_major_dir = '/home/autox/mirror/'
rsync_dest_major_dir = '/opt/mirror/'
if not rsync_server.endswith('/'):
rsync_server += '/'
if not rsync_dest_major_dir.endswith('/'):
rsync_dest_major_dir += '/'
rsync_cmd = subprocess.Popen('which rsync', shell=True, text=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
# print(rsync_cmd.read())
if len(rsync_cmd.stdout.read()) == 0:
print('rsync command not found,please enture the command is available')
exit(1)
sync_list = [
'ubuntu/dists/focal/',
'ubuntu/dists/focal-backports/',
'ubuntu/dists/focal-proposed/',
'ubuntu/dists/focal-security/',
'ubuntu/dists/focal-updates/',
'ubuntu/dists/bionic/',
'ubuntu/dists/bionic-backports/',
'ubuntu/dists/bionic-proposed/',
'ubuntu/dists/bionic-security/',
'ubuntu/dists/bionic-updates/',
'ubuntu/dists/xenial/',
'ubuntu/dists/xenial-backports/',
'ubuntu/dists/xenial-proposed/',
'ubuntu/dists/xenial-security/',
'ubuntu/dists/xenial-updates/'
]
for i in sync_list:
rsync_dest_full_dir = rsync_dest_major_dir + i
if not os.path.exists(rsync_dest_full_dir):
os.makedirs(rsync_dest_full_dir, mode=0o755)
cmd = subprocess.Popen(f'rsync -avzPn {rsync_server}{i} {rsync_dest_full_dir}', shell=True, text=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
# cmd_err = cmd.stderr.read().strip()
# if cmd_err is not None:
if cmd.stderr.read().strip() is not None:
print(cmd.stderr.read().strip())
print(f'"{i}" directory sync faild, stop syncing.')
exit(2)
else:
print(cmd.stdout.read())
print(f'"{i}" directory sync complete.')

Related

PyQt5 UI Freezes ADB & SCRCPY are also being used when freezing

I am trying to create a program using PyQt5, ADB, scrcpy, and python. When I click on connect, which starts a scrcpy server and mirrors the android device on the screen, my UI freezes until I close my scrcpy session/server. I will share both .py file codes that are used to make this work and look.
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5 import uic
import os
import sys
from ADBee import *
from twt_start import *
devs = devices()
log_window = []
# GET LIST OF CONNECTED SERIAL NUMBERS
os.chdir('resources/ui/')
class TB_Main_Window(QMainWindow):
def __init__(self):
super(TB_Main_Window, self).__init__()
uic.loadUi('main.ui', self)
self.find_button.clicked.connect(lambda: self.find_devices(devs))
self.connect_button.clicked.connect(self.connect_to_device)
self.disconnect_button.clicked.connect(self.disconnect_from_device)
self.connect_button.setEnabled(False)
self.disconnect_button.setEnabled(False)
#make = self.device_make.placeholderText.connect(self.get_selected_items)
self.show()
def find_devices(self, devs):
count = 0
try:
if len(devs) == 0:
print(" --- No Devices Found --- \n")
elif len(devs) > 0:
for d in devs:
self.device_listbox.addItem(devs[count])
count += 1
self.connect_button.setEnabled(True)
except:
print("\nCould Not Find Devices\n")
def get_selected_items(self):
serial = self.device_listbox.currentText()
print(serial)
return serial
# CONNECT TO SELECTED DEVICE (SERIAL)
def connect_to_device(self):
_serial = self.device_listbox.currentText()
self.find_button.setEnabled(False)
self.connect_button.setEnabled(False)
num_devices = self.device_listbox.count()
if num_devices == 1:
try:
twt()
except:
print("\nCould Not Connect To Device\n")
if num_devices > 1:
try:
self.find_button.setEnabled(False)
self.connect_button.setEnabled(False)
twt_ws(serial=_serial)
except:
print(f'Failed to connect to:{_serial}')
elif num_devices == 0:
print(f'\nNo Devices Found\n')
def disconnect_from_device(self):
self.device_listbox.setEnabled(True)
self.find_button.setEnabled(True)
self.connect_button.setEnabled(False)
try:
kill_server()
print(f"Device Disconnect Successfully")
except:
print(f"Can't Disconnect From Device")
app = QApplication([])
window = TB_Main_Window()
window.show()
sys.exit(app.exec_())
############################################################################################
from subprocess import Popen as send
import subprocess
import os
def twt(window_title='Twitedb3rn', width='480', height='900'):
try:
orientation()
console_send = send(
f"scrcpy --always-on-top --window-title={window_title} --window-width={width} --window-height={height} ",
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True)
_twt, errors = console_send.communicate()
print(f'\n\tTWT Started\n\n!---START---!\n\n{_twt}\n!---END---!')
console_send.wait()
except:
print(f'\nScrcpy Failed {errors}\n\n')
def twt_ws(window_title='Twitedb3rn', width='480', height='900', serial='99031FFBA0083T'):
try:
orientation_ws(serial)
new_directoy = os.chdir('resources/scrcpy')
console_send = send(
f'scrcpy --always-on-top --window-title={window_title} --window-width={width} --window-height={height} -s{serial}',
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True)
_twt_ws, errors = console_send.communicate()
console_send.wait()
print(f'\n\tTWT Started\n\n!---START---!\n\n{_twt_ws}\n!---END---!')
except:
print(f'\nTWT Failed\n\n')
print(errors)
#adb shell dumpsys window | grep 'mLandscapeRotation'
def orientation_ws(serial):
try:
console_send = send(
f"adb -s {serial} shell content insert --uri content://settings/system --bind name:s:accelerometer_rotation --bind value:i:0",
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True)
_orientation, errors = console_send.communicate()
console_send.wait()
print(f'\nScreen Rotation Disabled')
try:
home = send(f'adb -s {serial} shell input keyevent KEYCODE_HOME')
home.communicate()
home.wait()
console_send = send(
f"adb -s {serial} shell content insert --uri content://settings/system --bind name:s:user_rotation --bind value:i:1",
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True)
_orientation, errors = console_send.communicate()
console_send.wait()
print(f'\nScreen Set Landscape')
except:
print(f'\nScreen Landscape Failed')
print(errors)
except:
print(f'\nScreen Rotation Not Disabled')
print(errors)
return errors
def orientation():
try:
console_send = send(
f"adb shell content insert --uri content://settings/system --bind name:s:accelerometer_rotation --bind value:i:0",
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True)
_orientation, errors = console_send.communicate()
console_send.wait()
print(f'\nScreen Rotation Disabled')
try:
home = send(f'adb shell input keyevent KEYCODE_HOME')
home.communicate()
home.wait()
console_send = send(
f"adb shell content insert --uri content://settings/system --bind name:s:user_rotation --bind value:i:0",
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True)
_orientation, errors = console_send.communicate()
console_send.wait()
print(f'\nScreen Set Porttrait')
except:
print(f'\nScreen Portrait Failed')
print(errors)
except:
print(f'\nScreen Portrait Not Disabled')
print(errors)
return errors
All in all, it looks like your adb communication code is better formulated as something like the below.
Note I've elided all try/excepts; it's better to handle exceptions and errors "higher up" rather than just print out an error and let the program continue as if nothing bad had happened.
import subprocess
def set_adb_value(name, value):
# TODO: this is not safe against shell injection vulnerabilities if `name` and `value`
# are user-controlled.
subprocess.check_call(
f"adb shell content insert --uri content://settings/system "
f"--bind name:s:{name} "
f"--bind value:{value}"
)
def set_orientation(landscape=False):
# Disable screen rotation
set_adb_value("accelerometer_rotation", "i:0")
# Press home key
subprocess.check_call("adb shell input keyevent KEYCODE_HOME")
# Set rotation
set_adb_value("user_rotation", ("i:1" if landscape else "i:0"))
def start_scrcpy(window_title="Twitedb3rn", width="480", height="900", landscape=False):
set_orientation(landscape=landscape)
# TODO: this is not safe against shell injection vulnerabilities.
return subprocess.Popen(
f"scrcpy --always-on-top "
f"--window-title={window_title} "
f"--window-width={width} "
f"--window-height={height}",
)
No, you will need to understand what you're doing with your subprocesses first, and then use communicate etc. accordingly.
Many of those Popen (or send) uses you have right now would be better served by subprocess.check_call(), by the way.
This was the answer.
I removed:
_twt, errors = console_send.communicate()
console_send.wait()
and also:
_twt_ws, errors = console_send.communicate()
console_send.wait()

trying to get the output and return code for "nc -vz <host> <port>" command using subprocess.Popen in Python3

In Python3 using subprocess.Popen, I would like to capture the output and command return code for this "nc -z 192.168.25.14 22" command. Here is my sample code:
#!/usr/bin/env python
import urllib.request, urllib.error, urllib.parse
import subprocess
import time
# set up null file for pipe messages
nul_f = open('/dev/null', 'w')
# try loop for clean breakout with cntl-C
try:
with open('/mnt/usbdrive/output/Urls.txt') as f:
for line in f:
data = line.split()
commands = ['nc', '-vZ', data[1], data[0]]
print(commands)
try:
ncdmp = subprocess.Popen(commands , stderr=subprocess.PIPE, stdout=subprocess.PIPE,)
except OSError:
print ("error: popen")
exit(-1) # if the subprocess call failed, there's not much point in continuing
ncdmp.wait()
if ncdmp.returncode != 0:
print(" os.wait:exit status != 0\n")
else:
print ("os.wait:", ncdmp.pid, ncdmp.returncode)
print("STDERR is ", ncdmp.stderr)
print("STDOUT is ", ncdmp.stdout)
print("STDIN is ", ncdmp.stdin)
except KeyboardInterrupt:
print('Done', i)
# clean up pipe stuff
ncdmp.terminate()
ncdmp.kill()
nul_f.close()
and an example of the output is
*Commands is ['nc', '-vZ', '192.168.25.14', '22']
os.wait:exit status != 0
STDERR is <_io.BufferedReader name=12>
STDOUT is <_io.BufferedReader name=9>
STDIN is <_io.BufferedWriter name=8>*
I'm assuming that I have an error in my code or logic, but I can not figure it out. I have used similar code for other commands like ssh and ls without issues. For this "nc" command I get the same set of output/messages regardless of whether or not there is an open port 22 at the host address.
Thanks...RDK
OK, as I did not get any useful replies to this question, I changed the code from subprocess.Popen to subprocess.run as shown below. This modification worked for my requirements as ncdup.stderr contained the information I was looking for.
commands = shlex.split("nc -vz " + "-w 5 " + data[1] + " " + data[0])
try:
ncdmp = subprocess.run(commands , capture_output=True)
except OSError:
print ("error: popen")
exit(-1)
err_line = str(ncdmp.stderr)

indentation Error python 2.7

Hello I am having an indentation error on python 2.7
My program looks like this:
Imports: import sys, os
import subprocess
from threading import Thread
from re import split
Actual Code: def GetProcesses(Clean=True):
#
if Clean == True:
#
#
x = subprocess.Popen(["sudo", "ps", "aux"], stdout=subprocess.PIPE, shell=True)
(out, err) = x.communicate()
print(out)
print(out.split("\n"))
print("--------------")
Processes = out.split("\n")
print(Processes)
print("------")
print(Processes[0])
print("----------")
Header = Processes[0]
Process_list = Processes.remove(Processes[0])
return((Header, Process_list))
#
else:
#
#
if Clean == True: #added problem so future SE users can see it
x = subprocess.Popen(["ps", "aux"], stdout=subprocess.PIPE, shell=True)
(out, err) = x.communicate()
return(out)
I am not understanding the error, I have tried de-denting everyline 1 space, indenting back to the originals, and adding 1 space but it always says that it either expects an indent, or unexpected indent. P.S I am using only spaces.
Actual Error:File "MemoryHandling.py", line 31
x = subprocess.Popen(["ps", "aux"], stdout=subprocess.PIPE, shell=True)
^
IndentationError: expected an indented block
I have check several online questions/sources (mainly SE) for this error (below) both during and before asking this question, i found that they were case specific, downvoted / not answered, or were not usefull:
-- Python Indentation Error # i am using spaces
-- Python 2.7 Indentation error # i have manually checked indentation multiple times, and tried using the tab key
-- Unexpected indentation error, but indentation looks correct # once again not using tabs and spaces
-- Code Indent Error, code is indented? # not answered (bug?)
-- Python Indentation Error when there is no indent error # once more not using tabs and spaces
import sys, os
import subprocess
from threading import Thread
from re import split
#Actual Code:
def GetProcesses(Clean):
#
if Clean == True:
#
#
x = subprocess.Popen(["sudo", "ps", "aux"], stdout=subprocess.PIPE, shell=True)
(out, err) = x.communicate()
print(out)
print(out.split("\n"))
print("--------------")
Processes = out.split("\n")
print(Processes)
print("------")
print(Processes[0])
print("----------")
Header = Processes[0]
Process_list = Processes.remove(Processes[0])
return((Header, Process_list))
#
else:
#
#
x = subprocess.Popen(["ps", "aux"], stdout=subprocess.PIPE, shell=True)
(out, err) = x.communicate()
return(out)
The problem is here. After if part, there is no indentation provided.
else:
if Clean == True: #added problem so future SE users can see it
x = subprocess.Popen(["ps", "aux"], stdout=subprocess.PIPE, shell=True)
(out, err) = x.communicate()
return(out)

rsync called by subprocess Popen works when running script but does not when I generate an app with py2app

This is my code:
def uploadByRSync(host, user, passwd, src, dst, statusManager):
try:
os.environ["RSYNC_PASSWORD"] = passwd
print host, user, passwd, src, dst
parameters = ["rsync", "-azP", "--partial", src ,"{3}#{0}::{2}/{1}".format(host, dst, user, user)]
print " ".join(parameters)
process = subprocess.Popen(parameters, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
for line in unbuffered(process):
if "%" in line:
spl = line.split()
statusManager.uploadSpeed = spl[2]
statusManager.uploaded = spl[1]
return not process.wait()
except Exception as ex:
print ex
return False
newlines = ['\n', '\r\n', '\r']
def unbuffered(proc, stream='stdout'):
stream = getattr(proc, stream)
with contextlib.closing(stream):
while True:
out = []
last = stream.read(1)
# Don't loop forever
if last == '' and proc.poll() is not None:
break
while last not in newlines:
# Don't loop forever
if last == '' and proc.poll() is not None:
break
out.append(last)
last = stream.read(1)
out = ''.join(out)
print out
yield out
When running with the py2app version I can never get an output. When running as script everything works just fine. ps: this code runs on a separated thread of a Qt app. Does anyone have any idea why this is happening?
Most likely you have a stream buffering issue. Here is how you can output all lines of your process in real time:
import subprocess
import select
p = subprocess.Popen(parameters,
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
bufsize=0)
poll = [p.stdout.fileno(), p.stderr.fileno()]
while True:
# check if process is still running and read remaining data
if p.poll() is not None:
for l in p.stdout.readlines():
print(l)
for l in p.stderr.readlines():
print(l)
break
# blocks until data is being recieved
ret = select.select(poll, [], [])
for fd in ret[0]:
line = p.stdout.readline() if fd == p.stdout.fileno() else p.stderr.readline()
print(line)
Just made a test changing the Popen call by a simple 'ls',but I still cannot get the output when running py2app version. It works just fine when running python script. When I kill the py2app version app the output is just printed.
process = subprocess.Popen(["ls"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)

problem printing mount point of usb in python

I have a program written in python that uses dbus to detect inserted usb drives and prints the dir they are mounted on when they are detected. Here is the code:
import dbus
import gobject
import shutil
import os
import subprocess
import time
class DeviceAddedListener:
def __init__(self):
self.bus = dbus.SystemBus()
self.hal_manager_obj = self.bus.get_object(
"org.freedesktop.Hal",
"/org/freedesktop/Hal/Manager")
self.hal_manager = dbus.Interface(self.hal_manager_obj,
"org.freedesktop.Hal.Manager")
self.hal_manager.connect_to_signal("DeviceAdded", self._filter)
def _filter(self, udi):
device_obj = self.bus.get_object ("org.freedesktop.Hal", udi)
device = dbus.Interface(device_obj, "org.freedesktop.Hal.Device")
if device.QueryCapability("volume"):
return self.do_something(device)
def do_something(self, volume):
device_file = volume.GetProperty("block.device")
label = volume.GetProperty("volume.label")
fstype = volume.GetProperty("volume.fstype")
mounted = volume.GetProperty("volume.is_mounted")
mount_point = volume.GetProperty("volume.mount_point")
try:
size = volume.GetProperty("volume.size")
except:
size = 0
p1 = subprocess.Popen(["df", "-h"], stdout=subprocess.PIPE)
p2 = subprocess.Popen(["grep", device_file], stdin=p1.stdout, stdout=subprocess.PIPE)
p3 = subprocess.Popen(["awk", "{ print $6 }"], stdin=p2.stdout, stdout=subprocess.PIPE)
path = p3.communicate()[0]
print path
if __name__ == '__main__':
from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)
loop = gobject.MainLoop()
DeviceAddedListener()
loop.run()
The problem is that when I print the path variable (the mount point of the usb), it prints an empty string. However, when I execute these same commands (Popen(), etc) in the python interactive interpreter, it prints the path just fine (/media/03CB-604C). Why does this occur? Any edits / suggestions to my code would be much appreciated. Thanks in advance!
In your original question it seems likely that you're being beaten by a race condition.
The device is inserted and your code is executed before the mounting process has completed.
Try putting the Popen calls in a while loop (see below).
path = ""
count = 0
while count < 10 and path == "":
p1 = subprocess.Popen(["df", "-h"], stdout=subprocess.PIPE)
p2 = subprocess.Popen(["grep", device_file], stdin=p1.stdout, stdout=subprocess.PIPE)
p3 = subprocess.Popen(["awk", "{ print $6 }"], stdin=p2.stdout, stdout=subprocess.PIPE)
path = p3.communicate()[0]
count += 1
if path == "":
time.sleep(1)
print path
This is a bit of a resource-hungry solution, but it should do what you want.

Categories