I'm using Pyinstaller to make an .app bundle on Mac OS X, my app generates a config.ini, the script version worked flawlessly, but when it's an .app, it doesn't work.
I'm using ConfigParser to read and write.
I'm using Pyside for GUI.
It doesn't generate my .ini file, hence it doesn't read or write.
Yes, it's an Anime Notifier, got sick of checking it every time.
Code:
import sys
import urllib2
import ConfigParser
import re
import time
import thread
import atexit
from datetime import date
import lxml.html as lx
from PySide.QtCore import *
from PySide.QtGui import *
from pync import Notifier
def layout_widgets(self, layout):
return (layout.itemAt(i) for i in range(layout.count()))
def notify(self):
while True:
config.read('animeConfig.ini')
for newAnime in animeNotify.xpath('//*[#id="frontpage_left_col"]//*[#class="blue"]/text()'):
if config.has_section(newAnime):
for newEp in animeNotify.xpath('//*[#id="frontpage_left_col"]//*[text()="'+newAnime+'"]/parent::h2/following-sibling::h3/a/text()'):
if not config.has_option(newAnime, newEp):
Notifier.notify(newEp+' has been uploaded!', title=newAnime+' '+newEp.lower(), open='http://www.animeseason.com' +
animeNotify.xpath('//*[#id="frontpage_left_col"]//*[text()="'+newEp+'"]/#href')[0])
m = re.findall('\d+', newEp)
config.set(newAnime, newEp, int(m[0]))
with open('animeConfig.ini', 'wb') as configFile:
config.write(configFile)
time.sleep(300)
def checkChecked(self):
while True:
config.read('animeConfig.ini')
for checkbox in self.layout_widgets(self.vLayout):
if checkbox.widget().isChecked() and not config.has_section(checkbox.widget().text()):
config.add_section(checkbox.widget().text())
for anime in animeList.xpath('//*[#class="series_alpha"]/li/span/preceding-sibling::a/text()'):
if config.has_section(anime):
self.EUrl = animeList.xpath('//*[#class="series_alpha"]/li/*[text()="'+anime+'"]/#href')[0]
self.EUrl = lx.parse(urllib2.urlopen("http://www.animeseason.com" + self.EUrl))
for ep in self.EUrl.xpath('//tr/*[#class="text_center"]/a/text()'):
config.set(anime, 'episode '+ep, ep)
with open('animeConfig.ini', 'wb') as configFile:
config.write(configFile)
elif not checkbox.widget().isChecked() and config.has_section(checkbox.widget().text()):
config.remove_section(checkbox.widget().text())
with open('animeConfig.ini', 'wb') as configFile:
config.write(configFile)
time.sleep(300)
I'm also using the thread module so they can operate simultaneously.
Just like so:
thread.start_new_thread(self.notify, ())
thread.start_new_thread(self.checkChecked, ())
Left out the GUI part, because that isn't very interesting, I guess.
Related
I created these three functions in python (pool.py, funcA.py, config.py). My intent is that having two python files I would like the two functions to interact. Specifically, I have the pool.py file which has a while loop inside that simulates an always active process that should be blocked when the funcA.py file is called separately. The config.py file is used to create a global variable and use this variable in both files, with funcA.py I go to modify these variables cmd0 and cmd1 and instead with the file pool.py I repeatedly read these variables and check if they change. If you want to test the operation you can take these files and open two terminals in one run pool.py and in the other, you can run the funcA.py file then you can change the content of the cmd0 and cmd1 variables in the funcA.py file while the pool.py function is still running on the other terminal and you can see that the output of the pool.py file updates immediately.
Now my question is how can I make the contents of the funcA.py file become a function and run it directly as a function and have the same result? That is the one that by launching the new function that is inside the funcA.py file I modify the output of the pool.py function that is running on the other terminal.
config.py
def init():
global cmd0, cmd1
cmd0 = ''
cmd1 = ''
return cmd0, cmd1
pool.py
import os
import time
import sys
import numpy as np
import config
import funcA
from importlib import reload
while True:
funcA = reload(funcA)
print(str(config.cmd0))
print(str(config.cmd1))
if config.cmd0 == 'start':
print('stop')
time.sleep(10)
funcA.py
import os
import sys
import numpy as np
import config
config.cmd0 = 'start'
config.cmd1 = 'u1'
If i understood correctly, the following is working:
pool.py
python
import os
import time
import sys
import numpy as np
import config
import funcA
from importlib import reload
while True:
funcA = reload(funcA)
funcA.change_values("cmd0", "cmd1")
print(str(config.cmd0))
print(str(config.cmd1))
if config.cmd0 == 'start':
print('stop')
time.sleep(10)
funcA.py
import os
import sys
import numpy as np
import config
config.cmd0 = 'start'
config.cmd1 = 'u1'
def change_values(a, b):
config.cmd0 = a
config.cmd1 = b
As you can see, the function change_values is called in the pool.py without any check, then the cmd0 and cmd1 will change immediately.
I downloaded offline zim archives of websites such as wikipedia.com, stackoverflow.com, unix.stackexchange.com etc. and serve them via below script.
#!/usr/bin/env python3
import os
import subprocess
import sys
import threading
from zimply import ZIMServer
ZIMServer("/home/user/zim/wikipedia_en_all_novid_2018-05.zim", index_file="/home/user/zim/wikipedia_en_all_novid_2018-05.idx", port=8790, encoding="utf-8")
it works well but when I add another line
ZIMServer("/home/user/zim/math.stackexchange.com_eng_all_2018-08.zim", index_file="/home/user/zim/math.stackexchange.com_eng_all_2018-08.idx", port=7890, encoding="utf-8")
it doesn't load the second ZIMServer. I think it's a python multithreading issue. How can I run both of them in the single script?
By using multiprocessing — Process-based parallelism, plus port incrementation.
from multiprocessing import Process
import os
import subprocess
import sys
import threading
from zimply import ZIMServer
def f(port, file, idx):
ZIMServer(file, index_file=idx, port=port, encoding="utf-8")
if __name__ == '__main__':
p1 = Process(target=f, args=(8790,"/home/user/zim/wikipedia_en_all_novid_2018-05.zim",""))
p2 = Process(target=f, args=(8791,"/home/user/zim/whatever.zim",""))
p1.start()
p2.start()
The code only stops when a keyboardinterrupt is used.
A break was used though I took it out and the adc data was read and then the spi.close was skipped along with the update_sheet("PCEM SHT.1", ADCDATA)
I've tried using a different exception, raise exception based on the number of variables in ADCDATA, but with no effect
# import many libraries
#!/usr/bin/python
# -*- coding: utf-8 -*-
from __future__ import print_function
from googleapiclient.discovery import build
from httplib2 import Http
from oauth2client import file, client, tools
from oauth2client.service_account import ServiceAccountCredentials
import datetime
import spidev # import the SPI driver
def read_mcp3002(channel):
### Working ADC Code
return adc_data
def update_sheet(sheetname, my_list):
###Working Update google sheet code
try:
while True:
Result=1##3.23#for 3302 [mV]..... Voltage=(High Voltage-Low Voltage)/(2^(# of conversion bits))
voltage1=(read_mcp3002(0))
voltage1k=voltage1*Result
voltage2=(read_mcp3002(1))
voltage2k=voltage2*Result # This one #
ADCDATA += [[voltage1k, voltage2k]]
if len(ADCDATA) == 100000:
#print(ADCDATA)
ADCDATA = []
print("+10000")
except KeyboardInterrupt: # Ctrl-C
spi.close()
def main():
update_sheet("PCEM SHT.1", ADCDATA)
if __name__ == '__main__':
main()
The desired result would be to automatically stop at len(ADCDATA)=100000: if len(ADCDATA)==100000, it would run the code in the If statement, and also execute spi.close() and lastly run through def main()'s update_sheet("PCEM SHT1", ADCDATA).
I was able to deal with my problem by importing sys and placing a system exit(1) at the bottom of the & inside the if len(ADCDATA)==100000
if len(ADCDATA)==100000
print("PCEM DATA")
spi.close()
update_sheet"........")
sys.exit(1)
I'm using an updating script and trying to get it to work with cython. It seems the pyupdater script is ignored (no print and not updating). It works fine with standard python, but calling a pyx file it seems it skips over this so no print and update.
If python main.py (Calls a cython script there is no print and to a larger extent it does not update).
def main():
import collections
import os
import sys
import time
import bb.bb_module
import progressbar
import urllib3.poolmanager
from pyupdater.client import Client, AppUpdate
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.chrome.options import Options
from client_config import ClientConfig
if __name__ == '__main__':
main()
Cython pyx file:
import urllib3.poolmanager
orig_urlopen = urllib3.poolmanager.PoolManager.urlopen
def new_urlopen(self, method, url, redirect=True, **kw):
if "s3.amazonaws.com" in url and 'authorization' in self.headers:
self.headers.pop('authorization')
return orig_urlopen(self, method, url, redirect, **kw)
import sys
urllib3.poolmanager.PoolManager.urlopen = new_urlopen
import logging
import http.client as http_client
import logging
from selenium import webdriver
from client_config import ClientConfig
from pyupdater.client import Client, AppUpdate
import progressbar
import sys
bar = None
import sys
import os
import sys
def check_for_update():
stdout_save = sys.stdout
sys.stdout = open(os.devnull, 'w')
def cb(status):
global bar
from tqdm import tqdm
if bar is None:
bar = progressbar.ProgressBar(widgets = [progressbar.Percentage(), progressbar.Bar(), progressbar.FileTransferSpeed(), ' ', progressbar.ETA()
], fd=sys.stdout).start()
zz = float(status['percent_complete'])
bar.update(zz)
stdout_save = sys.stdout
sys.stdout = open(os.devnull, 'w')
client = Client(ClientConfig(), refresh=True,
headers={'basic_auth': 'brofewfefwefewef:Er8qUc9c48LHAtH5mGz5'})
sys.stdout = stdout_save
client.platform = "win"
app_update = client.update_check(ClientConfig.APP_NAME, ClientConfig.APP_VERSION, channel='stable')
if app_update is not None:
app_update.progress_hooks.append(cb)
if app_update.download():
if isinstance(app_update, AppUpdate):
app_update.extract_restart()
return True
else:
app_update.extract()
return True
return False
def main():
import sys
class DevNull:
def write(self, msg):
pass
print('Current version is ', ClientConfig.APP_VERSION)
if check_for_update():
pass
else:
pass
import os
from contextlib import contextmanager
import sys, os
driver = webdriver.Firefox()
if __name__ == "__main__":
main()
driver = webdriver.Chrome()
sys.stdout = sys.__stdout__
print('This will not print anything')
Output:
DevTools listening on ws://127.0.0.1:12284/devtools/browser/b2f98849-8daa-4442-b594-6e7a904c2091
This will not print anything
It looks as if pyupdater is being ignored when calling cython script. It does not print or update.
I've created a repo to reproduce these issues. How can I get it to update when using cython? I have also included a working pythonic version to see the difference if needed
I suspect:
if __name__ == "__main__":
main()
used in the cython script may be the issue as other than pyupdater the cython script runs perfectly.
I'm using Python 2.7.6 and I have two scripts:
outer.py
import sys
import os
print "Outer file launching..."
os.system('inner.py')
calling inner.py:
import sys
import os
print "[CALLER GOES HERE]"
I want the second script (inner.py) to print the name of the caller script (outer.py).
I can't pass to inner.py a parameter with the name of the first script because I have tons of called/caller scripts and I can't refactor all the code.
Any idea?
One idea is to use psutil.
#!env/bin/python
import psutil
me = psutil.Process()
parent = psutil.Process(me.ppid())
grandparent = psutil.Process(parent.ppid())
print grandparent.cmdline()
This is ofcourse dependant of how you start outer.py.
This solution is os independant.
On linux you can get the process id and then the caller name like so.
p1.py
import os
os.system('python p2.py')
p2.py
import os
pid = os.getppid()
cmd = open('/proc/%d/cmdline' % (pid,)).read()
caller = ' '.join(cmd.split(' ')[1:])
print caller
running python p1.py will yield p1.py
I imagine you can do similar things in other OS as well.
Another, a slightly shorter version for unix only
import os
parent = os.system('readlink -f /proc/%d/exe' % os.getppid())
If applicable to your situation you could also simply pass an argument that lets inner.py differentiate:
import sys
import os
print "Outer file launching..."
os.system('inner.py launcher')
innter.py
import sys
import os
try:
if sys.argv[0] == 'launcher':
print 'outer.py called us'
except:
pass