It is the first time I write as I really didn't find any solution to my issue.
I want to allow my user to launch some Python program from Excel.
So i have this VBA code at some point:
lg_ErrorCode = wsh.Run(str_PythonPath & " " & str_PythonArg, 1, bl_StopVBwhilePython)
If lg_ErrorCode <> 0 Then
MsgBox "Couldn't run python script! " _
+ vbCrLf + CStr(lg_ErrorCode)
Run_Python = False
End If
str_PythonPath = "C:\Python34\python.exe C:\Users\XXXX\Documents\4_Python\Scan_FTP\test.py"
str_PythonArg = "arg1 arg2"
After multiple testing, the row in error in Python is when I try to import another module (I precise that this VBA code is working without the below row in Python):
import fct_Ftp as ftp
The architecture of the module is as follow:
4_Python
-folder: Scan_FTP
- file: test.py (The one launch from VBA)
-file: fct_Ftp.py
(For information, I change the architecture of the file, and try to copy the file at some other position just to test without success)
The import has no problem when I launch Test.py directly with:
import sys, os
sys.path.append('../')
But from VBA, this import is not working.
So I figured out this more generic solution, that dont work as well from Excel/VBA
import sys, os
def m_importingFunction():
str_absPath = os.path.abspath('')
str_absPathDad = os.path.dirname(str_absPath)
l_absPathSons = [os.path.abspath(x[0]) for x in os.walk('.')]
l_Dir = l_absPathSons + [str_absPathDad]
l_DirPy = [Dir for Dir in l_Dir if 'Python' in Dir]
for Dir in l_DirPy:
sys.path.append(Dir)
print(Dir)
m_importingFunction()
try:
import fct_Ftp as ftp
# ftp = __import__ ("fct_Ftp")
write += 'YAAAA' # write a file YAAAA from Python
except:
write += 'NOOOOOO' # write a file NOOOOO from VBA
f= open(write + ".txt","w+")
f.close()
Can you please help me as it is a very tricky questions ?
Many thanks to you guys.
You are able to start your program from the command line?
Why not create a batch file with excel which you then start in a shell?
Related
I am attempting to import several variables from one file into another file, without running the first file twice. Specifically, I have a script called "run_all_files.py" which loops through files in a local directory to be run in sequence, and this is the script through which I want to execute the files in question. In the file "file_1.py", I want to import the variables A and B into "file_2.py" but I do not want "file_1.py" to re-run.
I have also attempted to invoke if __name__=='__main__': function, but cannot get variables A and B to import by themselves, and "file_1.py" still runs twice. Both "file_1.py" and "file_2.py" are located in the path listed and are executed when running "run_all_files.py".
"run_all_files.py"
import os
path = "C:\\users\\mdl518\\Desktop\\"
def run_the_files():
file_list = ['file_1.py', 'file_2.py']
for filename in file_list:
os.system('python' + ' ' + os.path.join(path,filename))
run_the_files()
"file_1.py"
import os
def run_first_file():
global A, B
A = 'Hello'
B = 'User'
C = 'Python Programmer'
print("This is the first file to run")
run_first_file()
"file_2.py"
import os
from file_1 import A,B
def run_second_file():
print('Welcome, and ', A + ' ' + B)
print("This second program runs smoothly")
run_second_file()
Current output:
This is the first file to run
This is the first file to run
Welcome, and Hello User
This second program runs smoothly
Desired output:
This is the first file to run
Welcome, and Hello User
This second program runs smoothly
** Update: Change file_list in "run_all_files.py" to file_list = ['file_2.py'] to achieve the desired output **
One possibility would be if you go via a class, is definitely not elegant, but works.
"file_1.py"
from var import sol
class v(object):
sol = 'Hello'
"file_2.py"
from var import v
print(v.sol)
I am currently attempting to pass a variable from my C# winforms application to my Python executable through process.start(). The script uses shutil to duplicate and rename a separate python file, the file will be renamed with respect to a variable (var, c# variable)...
I want to pass the "current" text-box value of my winforms
application to my Python script and run into a name error on my
python script. In my script, after clicking a button ,through
openFileDialog, I select a excel sheet file in the FileDialog and the
full path to the file is pasted in a textbox, "Textboxpath." Here I
want to pass the textbox value (the Textboxpath value) of my winforms application to my Python script.
My issue is defining the C# variable current value or value to my Python script. My windows form application runs perfectly with the current script though when I attempt to run my Python script and pass the C# variable through ".Arguments", my Python file returns with "NameError: name 'Textboxpath' is not defined." I have attempted to rewrite the process.start() function including the variable in my python script there has been no success to defining the variable, any help would be very appreciated!
**C#:**
...
#script for defining openFileDialog variable and using OpenFileDialog goes here
Textboxpath.Text = openFileDialog.FileName; #prints file (excel workbook) directory path to text box
...
string var;
var = Textboxpath.Text;
ProcessStartInfo StartInfo
= new ProcessStartInfo(#"C:\directorytask\dist\modifyfest.exe");
StartInfo.FileName = "C:\\directorytask\\dist\\modifyfest.exe";
StartInfo.Arguments = var;
Process.Start(StartInfo);
**Python script: modifyfest.exe** #packaged with pyinstaller, --onefile
import os
import sys
import shutil
x = var
f = x - '.xlsx'
l = f - 'C:\directorytask'
k = '.py'
y = 'test_'
z = y + l +k
#duplicating/renaming python file
original = 'C:/directorytask/test_five.py' #original python file
target = 'C:/directorytask/' + z #original python file being duplicated with name z
shutil.copyfile(original, target)
**Error:**
Traceback <most recent call last>:
File "modifyfest.py", line 5, in <module>
NameError: name 'Textboxpath' is not defined
[34652] failed to execute script modifyfest
I added the parser! This is how the Python script looks now, runs perfect...
**answer:**
import os
import sys
import shutil
from pathlib import Path
def parse(p):
q = p
return q
x = parse(sys.argv[1]) #imports first argument sent by c#, I attempted sys.argv[0] instead and it returned the first line of my c# ProcessStartInfo list, file name...
p = Path(x).stem
k = '.py'
y = 'test_'
z = y + p +k
original = 'C:/directorytask/test_five.py' #retailer specific duplicated task
target = 'C:/directorytask/' + z #task being created
shutil.copyfile(original, target)
I've changed a script by commenting out a section and adding some print statements above it for testing purposes, the problem is when I run the script from any other directory than the one it's in, python is running the old version of the script.
Clearing __pycache__ had no effect.
Here's the python script in question:
import discord
import watson
import configparser
import os
from discord.ext.commands import Bot
from getpass import getuser
print("WHY ISN'T THIS BEING CALLED!!")
#print(os.getcwd())
#os.chdir("/home/{}/discordBotStaging".format(getuser()))
#print(os.getcwd())
#if(not os.path.isfile("./config.ini")):
# print("No config file found, make sure you have one in the same directory as this python script\nexiting")
# quit()
config = configparser.ConfigParser()
config.read("./config.ini")
TOKEN = config["DEFAULT"]["DISCORD_KEY"]
BOT_PREFIX = ("!", "$")
client = Bot(command_prefix=BOT_PREFIX)
#client.command(name="memealyze",
description="When uploading image include command \"!memealyze\" | \"!Memealyze\" | \"!MemeAlyze\" | \"!ma\" as a comment",
brief="Neural network put to good use",
aliases=["Memealyze", "MemeAlyze", "ma"],
pass_context=True)
async def GetMemeContents(context):
await client.say("Sending image to the mothership, hold tight.")
if(not context.message.attachments):
await client.say(
"Couldn't find image attachement. Make sure you include \"!memealyze\" or any of it's variants as a comment when submitting an image")
return
imageUrl = str(context.message.attachments[0]["url"])
messageContent = ""
resultDict = watson.ReturnWatsonResults(imageUrl)
for key,val in resultDict.items():
messageContent += "{} : {}%\n".format(key, val)
await client.say("Done, the boys at IBM said they found this:\n" + messageContent)
client.run(TOKEN)
And here's the issue:
yugnut#RyzenBuild:~$ python3 discordBotStaging/main.py
No config file found, make sure you have one in the same directory as this python script
exiting
yugnut#RyzenBuild:~$
yugnut#RyzenBuild:~/discordBotStaging$ python3 main.py
WHY ISN'T THIS BEING CALLED!!
^Cyugnut#RyzenBuild:~/discordBotStaging$
EDITS:
#ShadowRanger suggestions:
Try moving the print above all the imports in your script.
This yields promising results, I do get output by trying this but right after that I still run into the same issue
You can't use relative paths like that if the config file is expected to be in the same directory as the script; you have to do config.read(os.path.join(os.path.dirname(__file__), 'config.ini'))
I think my ignorance is showing :^), I changed this in my script as well
After making these edits along with trying to run the script after commenting out my import configparser line I still get the same error.
I have recently installed xlwings on my Mac and am currently trying to write a small programme to update some data(via requests). As a test, I tried to update the cryptocurrency prices via an API and write them into excel.
Without using runpython, the code works. However as soon as I run my VBA code,
I get this error:
File "<string>", line 1
import sys, os;sys.path.extend(os.path.normcase(os.path.expandvars('/Users/Dennis/Documents/crypto;
^
SyntaxError: EOL while scanning string liberal
I have searched numerous threads and forums, but can't seem to find an answer to my problem.
For a better understanding,
my python code:
import requests, json
from datetime import datetime
import xlwings as xw
def do():
parameter = {'convert' : 'EUR'}
#anfrage über API
query_ticker = requests.get('https://api.coinmarketcap.com/v1/ticker', params = parameter)
#anfragedaten in JSON-format
data_ticker = query_ticker.json()
wb = xw.Book.caller()
ws0 = wb.sheets['holdings']
for entry in data_ticker:
# update eth price
if entry['symbol'] == 'ETH':
ws0.range('B14').value = float(entry['price_eur'])
#update btc price
if entry['symbol'] == 'BTC':
ws0.range('B15').value = float(entry['price_eur'])
if entry['symbol'] == 'NEO':
ws0.range('B16').value = float(entry['price_eur'])
if entry['symbol'] == 'XRP':
ws0.range('B17').value = float(entry['price_eur'])
now = datetime.now()
write_date = '%s.%s.%s' %(now.day, now.month, now.year)
write_time = '%s:%s:%s' %(now.hour, now.minute,now.second)
ws0.range('B2').value = write_date
ws0.range('B3').value = write_time
wb.save('holdings.xlsm')
#wb.close()
this is my vba code:
Sub update_holdings()
RunPython ("import update_holdings; update_holdings.do()")
End Sub
Solved this. I just wanted to post the solution for anyone who might be confronted with the same issue.
I went to check my xlwings.conf file, in order to see the setup for "INTERPRETER" and "PYTHONPATH". I never did editing on this, however, it was formatted incorrectly.
The correct format is:
"INTERPRETER","pythonw"
"PYTHONPATH",""
My config file was setup this way:
"PYTHONPATH","
"
"INTERPRETER","Python"
Also, the path to my python was set incorrectly by default. Even though my command line works with Anaconda python 3.6, "pythonw" used the interpreter set in .bash_profile referenced to python 2.7 which came pre-installed with macOS.
Editing the config file "INTERPRETER" solved this issue.
Thanks everyone.
So, I am passing a environment variable from bash to python;
#!/usr/bin/env python2
import os
#connect("weblogic", "weblogic", url=xxx.xxx.xxx.xxx:xxxx)
os.environ['bash_variable']
via wlst.sh I can print exported bash_variable, but how do I execute stored variable? Basically, I am trying to remove the original connect statement and pass a variable that has said information. Thanks
Question though, why wouldn't you called the script with the variable as an argument and use sys.argv[] ?
By example something like this.
import os
import sys
import traceback
from java.io import *
from java.lang import *
wlDomain = sys.argv[1]
wlDomPath = sys.argv[2]
wlNMHost = sys.argv[3]
wlNMPort = sys.argv[4]
wlDPath="%s/%s" %(wlDomPath,wlDomain)
wlNMprop="/apps/bea/wls/scripts/.shadow/NM.prop"
try:
print "Connection to Node Manager"
print ""
loadProperties(wlNMprop)
nmConnect(username=NMuser,password=NMpass,host=wlNMHost,port=wlNMPort,domainName=wlDomain,domainDir=wlDPath,mType='ssl',verbose='true')
except:
print "Fatal Error : No Connection to Node Manager"
exit()
print "Connected to Node Manager"
The NM.prop file is a 600 file with the username/password for the NM.
EDIT :
So from what I understand you want to do something like this :
URLS = ['t3s://Host1:Port1','t3s://Host2:Port2','t3s://Host3:Port3']
for urls in URLS:
connect('somebody','password',urls)
{bunch of commands}
disconnect()
And the values of the list URLS would be define by the environment.
The way I see it you have 3 choices :
Have 1 script per environment, more or less identical save for the URLS list
Have 1 script but with a conditionnal branching on sys.argv[1] (the environment as a parameter) and create the list there.
Have 1 script which use a parameter file for each environment according to the environment. Each parameter file containing the list in question.
Something like that :
propENV = sys.argv[1]
propPath = "/path1/path2"
propFile = "%s/%s" %(propPath,propENV)
loadProperties(propFile)
I would probably use the properties file option myself as it is more flexible from an operational standpoint...at least IMHO.