Repeating Processes on python but with mixed variables - arrays

Currently im trying to finish a script to pass links from a youtube playlist trough youtube_dl to be able to stream the audio from them on to a player on my raspberry pi, but I don't know how to repeat a process but changing the variable automatically without changing every single number on the array like so:
import os
import pafy
import youtube_dl as yt
from youtube_dl import YoutubeDL
links = ["http://www.youtube.com/watch?v=JaSfjAIcGpQ",
"http://www.youtube.com/watch?v=pzAo3Hj15R4",
"http://www.youtube.com/watch?v=hWdovALEen0",
"http://www.youtube.com/watch?v=JVpTp8IHdEg",
"http://www.youtube.com/watch?v=Pw-0pbY9JeU",
"http://www.youtube.com/watch?v=lrfhf1Gv4Tw",
"http://www.youtube.com/watch?v=ilw-qmqZ5zY",
"http://www.youtube.com/watch?v=UwsY_foobEw",
"http://www.youtube.com/watch?v=RSNmgE6L8AU",
"http://www.youtube.com/watch?v=d020hcWA_Wg",
"http://www.youtube.com/watch?v=O4irXQhgMqg",
"http://www.youtube.com/watch?v=9P16xvwMQ5A",
"http://www.youtube.com/watch?v=fregObNcHC8",
"http://www.youtube.com/watch?v=fLN6ec7-43s",
"http://www.youtube.com/watch?v=DcHKOC64KnE",
"http://www.youtube.com/watch?v=UYwF-jdcVjY",
"http://www.youtube.com/watch?v=jQcBwE6j09U",
"http://www.youtube.com/watch?v=lXgkuM2NhYI",
"http://www.youtube.com/watch?v=vabnZ9-ex7o",
"http://www.youtube.com/watch?v=neNJvLIKaOk",
"http://www.youtube.com/watch?v=k4V3Mo61fJM",
"http://www.youtube.com/watch?v=pstVCGyaUBM",
"http://www.youtube.com/watch?v=D8Ymd-OCucs",
"http://www.youtube.com/watch?v=SeRJb3U1v3A",
"http://www.youtube.com/watch?v=J0DjcsK_-HY",
"http://www.youtube.com/watch?v=f2JuxM-snGc",
"http://www.youtube.com/watch?v=Eyjj8BgsBGU",
"http://www.youtube.com/watch?v=dX3k_QDnzHE",
"http://www.youtube.com/watch?v=luM6oeCM7Yw",
"https://www.youtube.com/watch?v=5iC0YXspJRM",
"https://www.youtube.com/watch?v=BnOVufgbIzA",
"https://www.youtube.com/watch?v=wwK_Kmh0P90",
"https://www.youtube.com/watch?v=UYfh9YhUVdE"]
y = YoutubeDL({
'format': 'bestaudio',
})
url = links[0]
r = y.extract_info(url, download=False)
print(r['ext'])
print(r['url'])
I am trying to change the part of "links[0]"
so i can repeat this process but without changing the number manually, but instead doing it in python. Im still new at python.

As I understand you want to iterate over the list. You can make it with a for loop.
Like so:
for link in links:
url = link
r = y.extract_info(url, download=False)

Answer above seems okay, just to add on other ways to do it:
Shortest version:
extracted_details_list = [y.extract_info(url, download=False) for url in links] # list comprehension
A long version, could be easier to get the flow of for-loops:
for i in range(len(links)):
url = links[i]
r = y.extract_info(url, download=False)
print(r['ext'])
print(r['url']

Related

Maya Python Mash - How can I add a selection set using Maya Mash API (in python)

Adding the cmds.connectAttr at the end does connect the selection set in Maya in the UI, but that's all it does. It acts as it its not registering.
import maya.cmds as cmds
import MASH.api as mapi
sel = cmds.ls(sl=1, l=1, fl=1)
new_set = cmds.sets(sel, n="custom_set")
obj_name = sel[0].split(".")[0]
shape = cmds.listRelatives(obj_name, s=True, f=1)
print(shape)
shape = "pCylinderShape1" #distribute mesh
cmds.select("|pCylinder2") #main mesh MASH
#create a new MASH network
mashNetwork = mapi.Network()
mashNetwork.createNetwork(name="Custom_placement", geometry="Repro")
shape = "pCylinderShape1"
mashNetwork.meshDistribute(shape, 4)
cmds.connectAttr(new_set+".message", mashNetwork.distribute+".selectionSetMessage")
Closest answer I found was here but I am not a programmer to know what that means.
If anyone can help, I'd much appreciate it.
After a lot of investigation I did manage to find the answer from the provided link.
The code I wrote was only the first part of the solution.
hasMASHFlag = cmds.objExists('%s.mashOutFilter' % (new_set))
if not hasMASHFlag:
cmds.addAttr( new_set, longName='mashOutFilter', attributeType='bool' )
cmds.setAttr( '%s.arrangement' % (mashNetwork.distribute), 4 )
cmds.setAttr( '%s.meshType' % (mashNetwork.distribute), 7 )
Note sure is needed but I noticed when you connect a selection set by default it has an extra attribute called mashOutFilter.
The part that is needed is the .meshType that makes it work.

Hello, I'm creating this automation with selenium, and I came across this problem

The code is complete and functional but not the way I need it because at this point it ends up collecting all the hrefs with the tag "a" and there are dozens present on the page, but I need you to perform the action in just three. Is there any way to limit the amount?
...enter code here
....
**links_de_posts2 = []
hrefs2 = navegador.find_elements_by_tag_name("a")
pic_hrefs2 = [elem.get_attribute("href") for elem in hrefs2]
print("Encontrei as hrefs!!")
time.sleep(3)
for link in pic_hrefs2:
try:
if link.index("/p/") != -1:
links_de_posts2.append(link)
except:
continue
for pic_href in links_de_posts2:
navegador.get(pic_href)
time.sleep(5)**

How to continuously send an array of serial data into multiple functions, with the data being updated everywhere? [duplicate]

This question already has answers here:
How do you run your own code alongside Tkinter's event loop?
(5 answers)
Closed 1 year ago.
I want to code a script, that has several different functions in which an array filled with serial data has to be received.
The serial data comes from an arduino every 1 seconds. (don't worry. I changed the code to a reproducible example by using a random array.)
What I've succeeded in so far is, that the code does send the array into the function example ONCE the first time and displays it as I want it to.
What it does not do yet, is, that the information inside the function gets updated as it comes in from the arduino. When you see the code, you're gonna say, well the data is only sent once. BUT when I randomize the array every second inside a loop, the loop obviously blocks the rest of the code and the gui won't build. The fact is, that serial read updates the array WITHOUT a loop, which is highly appreciated.
The question is: How do I transport this updating into the function. Remember: It would be the natural solution for the code below to simply insert the serial read stuff INSIDE the function. BUT this is just the code that boils down the issue. The real code has several widgets invoked inside several functions and I ended up copy-&-pasting THE ENTIRE serial data signal conditioning code block into EVERY function that needs the data. This significantly increased the lag of the code, and thus is no solution.
The example script contains commented out sections to make it easier to follow what I've been trying to do to solve it so far:
import numpy as np
#import rhinoscriptsyntax as rs
import time
import tkinter as tk
import serial
"""
ser = serial.Serial(
port='/dev/ttyUSB0',
baudrate = 500000,
#parity=serial.PARITY_NONE,
#stopbits=serial.STOPBITS_ONE,
#bytesize=serial.EIGHTBITS,
timeout=1
)
ser.flushInput()
ser.flushOutput()
#I've been trying to embed the serial read stuff inside a function itself, which I'd LOVE to implement,
#but it has the same problem: either it is called just once as it is written here, ore a loop blocks the code
def serial_data():
#serialData = ser.readline()
#serialData = serialData.decode()
#floats = [float(value) for value in serialData.split(',')]
#arr = np.array(floats)
arr = np.random.rand(100)
time.sleep(1)
return arr
"""
#above commented out and replaced with random array below.
#serialData = ser.readline()
#serialData = serialData.decode()
#floats = [float(value) for value in serialData.split(',')]
#arr = np.array(floats)
arr = np.random.rand(100)
time.sleep(1)
print(np.round(arr, 3))
def nextWindow(root):
frame1 = tk.Frame(root, width=800, height=500)
frame1.pack()
text= tk.Text(frame1, width=80, height= 12, bd=0)
text.pack()
text.delete("1.0",tk.END)
#serialData = serial_data()
#text.insert(tk.INSERT, serialData)
text.insert(tk.INSERT, np.round(arr, 3))
text.update()
root = tk.Tk()
root.title('PythonGuides')
root.geometry('300x200')
root.config(bg='#4a7a8c')
nextWindow(root)
root.mainloop()
A minimal example as to how to use .after "loops" (explanation in code comments):
import tkinter as tk
# for the example
counter = 1
# your serial_data function, renamed to
# be more self-explanatory
def get_serial_data():
# put the serial reading stuff here
# the counter is just an example
global counter
counter += 1
return str(counter)
def update_text(txt):
# get data, clear text widget, insert new data
serial_data = get_serial_data()
txt.delete('0.0', 'end')
txt.insert('end', serial_data)
# schedule this function to run again in 100ms
# so it will repeat all of this effectively
# updating the text widget, you don't need to call `.update`
# note that this is not recursive
root.after(100, update_text)
def create_text():
text = tk.Text(root)
text.pack()
update_text(text)
root = tk.Tk()
create_text()
root.mainloop()

How to assign multiple variables in a loop for graphs in Python 3

I am relatively new to coding and I have a few issues I don't quite understand how to solve, yet. I'm trying to build code that will make graphs that will produce from a ticker list, with the data downloading from yahoo finance. Taking out of account manually assigning stock1 (and so forth) a ticker for a moment...
I want to figure out how to loop the data going into running the graph, so TSLA and MSFT in my code. So far I have the code below, which I already changed dfs and stocks. I just don't understand how to make the loop. If anyone has some good resources for loops, as well, let me know.
Later, I would like to save the graphs as a png with file names corresponding to the stock being pulled from yahoo, so extra points if someone knows how to change this code (savefig = dict(fname="tsla.png", bbox_inches= "tight") which goes after style = 'default'. Thanks for the help!
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import datetime as dt
import mplfinance as mpf
import yfinance as yf
#yahoo info
start = "2020-01-01"
end = dt.datetime.now()
stock1 = 'TSLA'
stock2 = 'MSFT'
df1 = yf.download(stock1, start, end)
df2 = yf.download(stock2, start, end)
stocks = [[stock1],[stock2]]
dfs = [[df1],[df2]]
changingvars = [[stocks],[dfs]]
#graph1
short_sma = 20
long_sma = 50
SMAs = [short_sma, long_sma]
for i in SMAs:
dfs["SMA_"+ str(i)] = dfs.iloc[:,4].rolling(window=i).mean()
graph1 = mpf.plot(dfs, type = 'candlestick',figratio=(16,6),
mav=(short_sma,long_sma),
volume=True, title= str(stocks),
style='default')
plt.show()
Not sure why you are calculating your own SMA's, and grouping your stocks and dataframes, if your goal is only to create multiple plots (one for each stock). Also, if you are using mplfinance, then there is no need to import and/or use matplotlib.pyplot (nor to call plt.show(); mplfinance does that for you).
That said, here is a suggestion for your code. I've added tickers for Apple and Alphabet (Google), just to demonstrate how this can be extended.
stocklist = ['TSLA','MSFT','AAPL','GOOGL']
start = "2020-01-01"
end = dt.datetime.now()
short_sma = 20
long_sma = 50
for stock in stocklist:
df = yf.download(stock, start, end)
filename = stock.lower() + '.png'
mpf.plot(df,type='candlestick',figratio=(16,6),
mav=(short_sma,long_sma),
volume=True, title=stock,style='default',
savefig=dict(fname=filename,bbox_inches="tight")
)
The above code will not display the plots for each stock, but will save each one in its own .png file locally (where you run the script) for you to view afterwards.
Note also that it does not save the actual data; only plots the data and then moves on to the next stock, reassigning the dataframe variable (which automatically deletes the previous stock's data). If you want to save the data for each stock in a separate csv file, that is easy to do as well with Pandas' .to_csv() method.
Also, I am assuming you are calling yf.download() correctly. I am not familiar with that API so I just left that part of the code as you had it.
HTH. Let me know. --Daniel

JSON array keyerror in Python

I'm fairly new to Python programming and am attempting to extract data from a JSON array. Below code results in an error for
js[jstring][jkeys]['5. volume'])
Any help would be much appreciated.
import urllib.request, urllib.parse, urllib.error
import json
def DailyData(symb):
url = https://www.alphavantage.co/queryfunction=TIME_SERIES_DAILY&symbol=MSFT&apikey=demo
stockdata = urllib.request.urlopen(url)
data = stockdata.read().decode()
try:
js = json.loads(data)
except:
js = None
jstring = 'Time Series (Daily)'
for entry in js:
i = js[jstring].keys()
for jkeys in i:
return (jkeys,
js[jstring][jkeys]['1. open'],
js[jstring][jkeys]['2. high'],
js[jstring][jkeys]['3. low'],
js[jstring][jkeys]['4. close'],
js[jstring][jkeys]['5. volume'])
print('volume',DailyData(symbol)[5])
Looks like the reason for the error is because the returned data from the URL is a bit more hierarchical than you may realize. To see that, print out js (I recommend using a jupyter notebook):
import urllib.request, urllib.parse, urllib.error
import ssl
import json
import sqlite3
url = "https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=MSFT&apikey=demo"
stockdata = urllib.request.urlopen(url)
data = stockdata.read().decode()
js = json.loads(data)
js
You can see that js (now a python dict) has a "Meta Data" key before the actual time series begins. You need to start operating on the dict at that key.
Having said that, to get the data into a table like structure (for plotting, time series analysis, etc), you can use pandas package to read the dict key directly into a dataframe. The pandas DataFrame constructor accepts a dict as input. In this case, the data was transposed, so the T at the end rotates it (try with and without the T and you will see it.
import pandas as pd
df=pd.DataFrame(js['Time Series (Daily)']).T
df
Added edit... You could get the data into a dataframe with a single line of code:
import requests
import pandas as pd
url = "https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=MSFT&apikey=demo"
data = pd.DataFrame(requests.get(url).json()['Time Series (Daily)']).T
DataFrame: The contructor from Pandas to make data into a table like structure
requests.get(): method from the requests library to fetch data..
.json(): directly converts from JSON to a dict
['Time Series (Daily)']: pulls out the key from the dict that is the time series
.T: transposes the rows and columns.
Good luck!
Following code worked for me
import urllib.request, urllib.parse, urllib.error
import json
def DailyData(symb):
# Your code was missing the ? after query
url = "https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol={}&apikey=demo".format(symb)
stockdata = urllib.request.urlopen(url)
data = stockdata.read().decode()
js = json.loads(data)
jstring = 'Time Series (Daily)'
for entry in js:
i = js[jstring].keys()
for jkeys in i:
return (jkeys,
js[jstring][jkeys]['1. open'],
js[jstring][jkeys]['2. high'],
js[jstring][jkeys]['3. low'],
js[jstring][jkeys]['4. close'],
js[jstring][jkeys]['5. volume'])
# query multiple times, just to print one item?
print('open',DailyData('MSFT')[1])
print('high',DailyData('MSFT')[2])
print('low',DailyData('MSFT')[3])
print('close',DailyData('MSFT')[4])
print('volume',DailyData('MSFT')[5])
Output:
open 99.8850
high 101.4300
low 99.6700
close 101.1600
volume 19234627
Without seeing the error, it's hard to know what exact problem you were having.

Resources