How to avoid this circular import? - python

Asset variable must be declared from mother file (this is a simplified version).
File cannot be merged.
This mother file works :
import pandas as pd
import datetime as dt
import yfinance as yf
data=yf.Ticker("^NDX")
dataHist= data.history(interval="1d",start= dt.date.today()-dt.timedelta(days = 50) ,end= dt.date.today()-dt.timedelta(days = 0))
df = pd.DataFrame(dataHist[["Open","High","Low","Close"]])
import child_file
if __name__=="__main__":
df["expo"] = child_file.exponential_moving_average
print(df)
With this child file :
import pandas as pd
import parent_file
exponential_moving_average = pd.Series.ewm(parent_file.df["Close"],span=12).mean()
But if replace in mother file:
data=yf.Ticker("^NDX")
by this to be able to choose the asset :
if __name__=="__main__":
asset = "^"+str(input()).upper()
data=yf.Ticker(asset)
It says
NameError: name 'asset' is not defined
(from child file point of view)
How do i reorganize the code ?
I tried a lot this has went for several days now

Since you are not defining anything new or implementing any modular functions in your child file, I would suggest moving that to the parent file and deleting the child file.
However, if you so choose to maintain the two, you should
load dataFrame in your child file, but not your parent file.
You could potentially define a function in your child file that takes parameters required for loading your ticker data, and call that function from your parent file.
Edit:
I would write a function in your child file.
def moving_average(close_price):
return pd.Series.ewm(close_price, span=12).mean()

Related

How to import variables from one file into another

I'm trying to take a separate text file, with a list of defined variables, and import them into the main py file. Not trying any classes or functions, just predefined variables. I tried a number of different solutions but the syntax isn't working for all the different types.I'm working on a Linux device and .py is in the file name. I dont know if that's causing an issue or not so I renamed it and still is not working. Files are here.
list of variables:
/home/example/file.module.py
actual code file to run:
/home/example/filetorun.py
I've tried on filetorun:
import file.module.py
import 'file.module.py'
from file.module.py import *
from 'file.module.py' import *
import ./file.module.py
import /home/example/file.module.py
(renamed file to file.module) import /home/example/file.module
All these are not working, not sure if have to make a function to return all these values or what.
Your issue is that you have a dot in the file name. Either change the name of the file and follow what I have posted below, or check out importlib.util from this post: Import with dot name in python
https://www.geeksforgeeks.org/how-to-import-variables-from-another-file-in-python/
Import the file (no need to specify Path if in same directory) and then use the file name pre-the variable.
# calval.py file where to import variables
# import swaps.py file from which variables
# to be imported
# swaps.py and calval.py files should be in
# same directory.
import swaps
# Import x and y variables using
# file_name.variable_name notation
new_x = swaps.x
new_y = swaps.y
print("x value: ", new_x, "y value:", new_y)
# Similarly, import swapVal method from swaps file
x , y = swaps.swapVal(new_x,new_y)
print("x value: ", x, "y value:", y)

Importing functions into Jupyter Notebook getting a name error

I am working Jupyter notebook on AWS Sagemaker instance. For convenience I wrote a .py file with couple of functions as defined;
#function to gather the percent of acts in each label feature combo
def compute_pct_accts(data, label_cnt):
"""
data is the output from aggregate_count
labe_cnt gives the breakdown of data for each target value
"""
label_data_combined = pd.merge(data, label_cnt, how='inner', left_on= 'label', right_on = 'label')
label_data_combined['Act_percent'] = np.round((label_data_combined['ACT_CNT']/label_data_combined['Total_Cnt'])*100,2)
return label_data_combined
#write a function to perform aggregation for target and feature column
def aggregate_count(df, var, target):
"""
df is the dataframe,
var is the feature name
target is the label varaible(0 or 1)
"""
label_var_cnt = df.groupby([var,target],observed=True)['ID'].count()
label_var_cnt = label_var_cnt.reset_index()
label_var_cnt.rename(columns={'ID':'ACT_CNT'},inplace=True)
return label_var_cnt
Both these functions are stored in a .py file called file1.py. Then to retrieve them in my notebook I typed;
from file1 import *
import pandas as pd
This command did import both functions. But when I tried to run the function;
compute_pct_accts(GIACT_Match_label_cnt, label_cnt)
I am getting a Name error;
pd not found
Please note that I have imported pandas as pd in my jupyter notebook. I am aware of using the option
%run -i compute_pct_accts_new.py
but that forces me to write a new python file with that function. My question is, can we have one python file with all functions defined in it, so that we can import all of them at once and use interactively in notebook.
Help is appreciated.
Try importing pandas in the .py file containing the function you want to import.

Why is the order of importing files resolving a NameError?

I have three files, one being the main file that needs to be run, and the other two contain utility functions, as follows. All the files are in the same directory and I am running it on PyCharm.
# delta_plots.py - This is the main file
...
from delta_plots_utility_1 import *
from delta_plots_utility_2 import *
...
def print_parameter_header(params, flag):
batch_size, epochs, lr = params[0], params[1], params[2]
print("{} - Batch size: {}, Epochs: {}, Learning rate: {}".
format(flag.upper(), batch_size, epochs, lr))
...
if __name__ == '__main__':
# call the utility functions based on a condition
if (condition1):
utility_function_1()
elif (condition2):
utility_function_2()
# delta_plots_utility_1.py - Utility file 1
# this import statement is to import the print_parameter_header() function
# from the main file
from plot_delta_mp import *
def utility_function_1():
# this function makes a call to the print_parameter_header() function
...
print_parameter_header(params, flag)
...
# delta_plots_utility_2.py - Utility file 2
from plot_delta_mp import *
def utility_function_2():
# this function also makes a call to the print_parameter_header() function
...
print_parameter_header(params, flag)
...
The problem is when in the main file, if condition1 is true, then I am forced to put the import statement for utility file 1 before the import statement for utility file 2, and vice versa.
Otherwise, I get the following error:
NameError: name 'print_parameter_header' is not defined
I also tried importing the files as modules and then accessing the function as module.print_parameter_header(), but that does not help either.
I had the following questions regarding this:
From what I understand, the order of the import statements is not important. So why is this happening? Why does changing the order resolve the error?
Could this be because of the loop-like importing? Since I am importing the main file in the utility functions too.
If yes, then is it okay to define print_parameter_header() in the utility files? Although it would be redundant, is that a good practice?
It seems that all of your issues come from that initial misunderstanding: "From what I understand, the order of the import statements is not important."
In python, an import statement
can happen anywhere in the code (not necessarily at the beginning), so if you enter into circular dependency issues it might be a good idea to import the latest possible if you have no other design choice
creates symbols in the code. So from xxx import a will create variable a locally, just like writing a = 0. It is exactly the same.
So maybe a good solution for you would be to stop using from <xxx> import * or import <xxx>, which both import all symbols from the other module, but to import selected symbols in precisely controlled places. Such as from <xxx> import a, b and later in your code from <xxx> import c.
Sorry for not taking the time to adapt the above answer to your precise code example, but hopefully you'll get the idea.

Import single OBJ files into Maya, moving and rotating it with Python/MEL

Hi I have this code to import OBJ files into maya with Python
**
import maya.cmds as cmds
pathOfFiles = "/Path/to/the/files/folder/"
fileType = "obj"
files = cmds.getFileList(folder=pathOfFiles, filespec='*.%s' % fileType)
if len(files) == 0:
cmds.warning("No files found")
else:
for f in files:
cmds.file(pathOfFiles + f, i=True)
**
It imports all the obj files which are into that folder.
However, what I need is:
Import an individual OBJ file at once
Move and rotate the imported file
Apply a Material already created in Maya
Render
Delete the file
6 Repeat the process with the next file
Is it possible to do it with Python or MEL
This looks like a fun challenge, so here's my attempt at answering it:
import maya.cmds as cmds
import glob
#1. Import an individual OBJ file at once
def importFile(i):
cmds.file(i, i=True, groupReference=True, groupName="myobj")
#2. Move and rotate the imported file
def moveFile():
cmds.select("myobj")
# Add the X,Y,Z cordinates to change scale, translate and rotate below
cmds.scale(1,1,1)
cmds.move(0,0,0)
cmds.rotate(0,90,0)
#3. Apply a Material already created in Maya
def materialFile():
cmds.select("myobj")
myMaterial = "lambert2" + "SG" #replace lambert2 with your material
cmds.sets(forceElement=myMaterial)
#4. Render
def renderFile(i):
cmds.setAttr("defaultRenderGlobals.imageFilePrefix", i, type="string")
cmds.render(batch=True)
#5. Delete the imported file
def deleteFile():
cmds.select("myobj")
cmds.delete()
# Add the path to your obj files. Make sure to leave the /*.obj at the end
myglob = glob.glob("/Users/OSX/Desktop/objs/*.obj")
for i in myglob:
importFile(i)
moveFile()
materialFile()
renderFile(i)
deleteFile()
Because you have a list of individual things you need the script to do I've divided up each requirement on your list into its own function. This should make the script more modular and hopefully easy to edit and reuse.
Python works much better for this kind of task because MEL doesn't have functions, instead it has procedures which act like functions but don't work as well from what I've experienced.

Passing a list from an imported module

I have a file with a function defined, which imports and organizes data into a list of lists. It returns that list of lists, and this all functions fine within the same file (if I write a main function and call the import function, no problems).
def import_viscosity_data(size_of_header):
...
return (list_of_lists)
I'm trying to call this function from another file in the same directory, using the following:
import load_files
print(load_files.import_viscosity_data(7))
Unfortunately, this keeps returning 'None', and if I try to get the length of the returned array, it throws an error:TypeError: object of type 'NoneType' has no len()
I'm guessing that it's passing me a reference to the list, and the actual list gets deleted as soon as the function terminates, but I'm not sure how to resolve this problem. Any help would be greatly appreciated!
Here's the code:
import os
import tkinter
from tkinter import filedialog
#import decimal
from decimal import *
def import_viscosity_data(size_of_header):
### This function imports viscosity data from multiple files, skipping the
### header passed inof the form shearRate '\t' viscosity and puts it into
### an array of the form test_num[result_type[data]]] where result type
### is 0 (shearRate) or 1 (viscosity)
header_size = size_of_header
root = tkinter.Tk()
root.withdraw()
file_path = root.tk.splitlist(filedialog.askopenfilenames(
parent=root, title='Choose a file(s):'))
test_num = []
result_type = []
data_1 = []
data_2 = []
for file_name in file_path:
f = open(file_name)
## Skip the header, which consists of header_size lines
for i in range(header_size):
next(f)
lines = [line.strip() for line in f]
f.close()
## For a line, slice all characters before the tab, then after the tab
## convert to Decimal, and append to the data list
for index in range(len(lines)):
data_1.append(Decimal(lines[index][0:lines[index].find('\t')]))
data_2.append(Decimal(lines[index][lines[index].find('\t') + 1:]))
result_type.append(data_1)
result_type.append(data_2)
test_num.append(result_type)
data_1, data_2, result_type = [], [], []
return(test_num)
Here's some sample data to try it on (any data in 2 columns with a tab in between):
0 1.2381
0.004 1.23901
0.008 1.23688
0.012 1.23734
0.016 1.23779
0.02 1.23901
0.024 1.23932
0.028 1.23886
0.032 1.23688
0.036 1.2384
Again, within this program (running in an IDE, or if I write a small main() function), this returns a list of list of lists, and works just fine. However, when I import the function in a different file, it returns None, without throwing any errors. The function name pops up automatically in the IDE after the import load_files, so it seems to be importing properly.
Note
*This secondary problem was resolved. The file load_files.py was within a directory called load_files. The import statement was changed to from load_files import load_files and it now functions properly.*
Today my problem has gotten even worse. Now, I can't get any functions from the first file to be recognized in the second. Even a simple set of code like:
#load_files.py
def test_func():
print('test successful')
#test.py
import load_files
load_files.test_func()
is throwing this error:
Traceback (most recent call last):
File "C:\Users\tmulholland\Documents\Carreau - WLF\test.py", line 8, in <module>
load_files.test_func
AttributeError: 'module' object has no attribute 'test_func'
load_files.py is in it's own folder (of the same name) with a blank __init__.py file
Note I should add that I'm using the Pyzo IDE because I want to use the scipy library to do curve fitting / optimization problems. I can't get any functions to import correctly today into Pyzo, no matter how simple. Has anybody else had this problem?
The problem was the test.py file's import statement. At first, I confused the issue by having, in the same directory as the test.py, load_files.py and also a directory called load_files which contained load_files.py as well as a blank file called __init__.py.
The original script read
import load_files
print(load_files.import_viscosity_data(7))
I eliminated the load_files.py which shared a directory with test.py. Now, I have test.py in the parent directory, then a sub-directory called load_files which contains load_files.py. The new script reads:
from load_files import load_files
print(load_files.import_viscosity_data(7))
Now, the list of lists is passed in to the local space, so a statement like
list_test = load_files.import_viscosity_data(7)
works fine.
I couldn't get things to work correctly when I just had the two .py files in the same directory (e.g. test.py and load_files.py in the same directory, no sub-directory). The import statement of import load_files threw an error that the module doesn't exist. Anyway, it all works well now with the above code.
Special thanks to Martijn Pieters for the feedback.

Categories