37

I'm sure this is very simple but I've been unable to get it working correctly. I need to have my main python script call another python script and pass variables from the original script to the script that I've called

So for a simplistic example my first script is,

first.py
x = 5
import second

and my second script is,

second.py 
print x

and I would expect it to print x but I get

NameError: name 'x' is not defined

I'm not sure if import is right way to achieve this, but if someone could shed light on it in a simple way that would be great!

thanks,


EDIT

After reading the comments I thought I would expand on my question. Aswin Murugesh answer fixes the import problem I was having, however the solution does not have the desired outcome as I can not seem to pass items in a list this way.

In first.py I have a list which I process as follows

for insert, (list) in enumerate(list, start =1):
    'call second.py passing current list item'

I wanted to pass each item in the list to a second python file for further processing (web scraping), I didn't want to do this in first.py as this is meant to be the main 'scan' program which then calls other programs. I hope this now make more sense.

Thanks for the comments thus far.

DavidJB
  • 2,272
  • 12
  • 30
  • 37
  • Is there any way these two scripts could become functions inside a single script? – summea Apr 16 '13 at 22:26
  • 2
    @summea Not really a helpful response. Yes, I suppose the OP could try to work around not understanding the basics of the Python import system by *never using imports, ever*, but do you really think that's a helpful suggestion when all he needs to progress from his current confusion is a tiny code snippet showing how to use imports? – Mark Amery Apr 16 '13 at 22:30
  • 7
    Unlike some languages, Python's `import` doesn't just dump the source of the imported file in the middle of the including file and executes the whole thing. The imported file knows nothing of its surroundings, which is why this code breaks. In your case I'm not sure if imports are the right thing to use. Proper modularization would suggest designing second.py so that it can be passed `x` as an argument to functions/objects defined inside it. – Stjepan Bakrac Apr 16 '13 at 22:38
  • @MarkAmery Only trying to suggest a different approach, if possible. – summea Apr 16 '13 at 22:38
  • 1
    Stjepan Bakrac's response is the most helpful thing that's been said here. You haven't fleshed out your scenario enough for us to be sure what's appropriate, but from what you've written I'd guess that `first` is essentially a 'main' module - a conceptually natural entry point for your program - but that you want to separate some of the logic out into `second`. That's fine, but if so you need to create a function (or functions, or a class or classes) in `second` that takes as arguments the variables from `first` that it needs. – Mark Amery Apr 16 '13 at 22:42
  • updated with further details, thanks for your comments thus far – DavidJB Apr 17 '13 at 18:52
  • I am a little bit confused, why can't you just create a function in your second.py and pass the variables as parameters? Or do you need to manipulate the values und the changes need to be known in first.py? Then I would still prefer a function and return a list or dict. – dr fu manchu Dec 06 '21 at 12:05

5 Answers5

43

When you call a script, the calling script can access the namespace of the called script. (In your case, first can access the namespace of second.) However, what you are asking for is the other way around. Your variable is defined in the calling script, and you want the called script to access the caller's namespace.

An answer is already stated in this SO post, in the question itself:

Access namespace of calling module

But I will just explain it here in your context.

To get what you want in your case, start off the called script with the following line:

from __main__ import *

This allows it to access the namespace (all variables and functions) of the caller script.

So now your calling script is, as before:

x=5
import second

and the called script is:

from __main__ import *
print x

This should work fine.

Community
  • 1
  • 1
Abhranil Das
  • 5,702
  • 6
  • 35
  • 42
  • 1
    Actually I just checked this with a list and it dosen't seem to work, the second program is only called ONCE for the first item in the list, whereas I need it for each item in sequence as a new instance. It also seems that if I have a timer.sleep() call in second it stops the the main program (first)...? – DavidJB Apr 17 '13 at 20:56
  • Doesnt work for me…always get ñame ‘x’ is not defined – Tommy Dec 06 '22 at 12:57
14

use the following script:

first.py:

x=5

second.py

import first
print first.x

this will print the x value. Always imported script data should be referenced with the script name, like in first.x

Aswin Murugesh
  • 10,831
  • 10
  • 40
  • 69
7

To avoid namespace pollution, import the variables you want individually: from __main__ import x, and so on. Otherwise you'll end up with naming conflicts you weren't aware of.

Grant Palmer
  • 208
  • 2
  • 7
2

Try use exec Python3.5:

first.py

x=5
exec(open('second.py').read())

second.py

print(x)

You can also pass x by using:

x=5
myVars = {'x':x}
exec(open('second.py').read(), myVars)

Not sure if this is a good way.

Z-Jiang
  • 189
  • 2
  • 10
0

Finally,

I created a package for Python to solve this problem.


Install Guli from PIP.

$ pip install guli

Guli doesn't require installing any additional PIP package.

With the package you can

Guli can be used to pass between different Python scripts, between many processes or at the same script. pass variables between main Process and another (Multiprocess) Process.

  • Pass variables between different Python scripts.
  • Pass variables between 'Main Process' and another (Multiprocess) Process.
  • Use variables at the same script.
  • Create / Delete / Edit - GuliVariables.

Example

import guli
import multiprocessing

string = guli.GuliVariable("hello").get()
print(string) # returns empty string ""

def my_function():
  ''' change the value from another process '''
  guli.GuliVariable("hello").setValue(4)

multiprocessing.Process(target=my_function).start()

import time
time.sleep(0.01) # delay after process to catch the update


string = guli.GuliVariable("hello").get()
print(string) # returns "success!!!"

Hope I solved the problem for many people!

red alert
  • 25
  • 4